[Go语言]从Docker源码学习Go——指针和Structs
这两天在看reflect这个包在Docker中的使用时,遇到了各种问题,最后虽然知道怎么用了。
但是对于这块的原理还不是太懂,于是把"THE WAY TO GO"中关键的几章看了下。
继续坚持往下写,争取能说明白。
源码
还是先看Docker中源码, docker/api/client/cli.go
type DockerCli struct {
proto string
addr string
configFile *registry.ConfigFile
in io.ReadCloser
out io.Writer
err io.Writer
isTerminal bool
terminalFd uintptr
tlsConfig *tls.Config
scheme string
} ... func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
...
return &DockerCli{
proto: proto,
addr: addr,
in: in,
out: out,
err: err,
isTerminal: isTerminal,
terminalFd: terminalFd,
tlsConfig: tlsConfig,
scheme: scheme,
}
}
先定义了一个struct,然后定义一个初始化的方法(方法内部初始化了一个struct,并返回其地址。)
指针
首先介绍一下go中的指针
我们在程序中定义一个变量,它在内存中被分配了一块空间,这块空间内存储的值就是变量的值,而这块空间的地址就可以赋值给一个指针。
指针内存放的是一个变量的内存地址,而不是真实的变量值。
声明一个指针用下面的方式( type 前面带 * 符号)
var intP *int
给指针赋值用 & 符号
i1 :=
intP = &i1
通过在指针变量前面添加 * 符号,你可以获得指针指向变量的值。
int1 == *(&int1)
在传值过程中尽量使用指针,这可以大大的减少内存开支,并提高传值速度。
不过有一个缺点是,在获得值时,由于多加了一层关系,所以会在这部分的性能上稍微慢一点。
struct使用
struct格式
type identifier struct {
field1 type1
field2 type2
...
}
struct初始化, 看下面例子中的3种情况就明白了。
// main
package main import "strings" type Person struct {
firstName string
lastName string
} func upPerson(p *Person) {
p.firstName = strings.ToUpper(p.firstName)
p.lastName = strings.ToUpper(p.lastName)
} func main() {
//1 - struct as a value type:
var pers1 Person
pers1.firstName = "Lemon"
pers1.lastName = "Bar"
upPerson(&pers1) //2 - struct as a pointer:
pers2 := new(Person)
pers2.firstName = "Lemon"
pers2.lastName = "Bar"
//(*pers2).lastName = "Bar" //this is also valid
upPerson(pers2) //3 - struct as a literal:
pers3 := &Person{"Lemon", "Bar"}
//pers3 := &Person{firstName:"Lemon",lastName:"Bar"} //this is also valid
upPerson(pers3)
}
注:new出来的是指针
我们除了可以直接初始化外,也可以通过定义工厂方法的形式来进行初始化
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
...
}
注:如果想让这个struct在所属的package外,只能通过工厂方法来初始化,可以把struct名字的首字母改成小写,也就是private的,package外就只能通过工厂方法进行初始化了。
匿名fields
匿名的fields可以实现其它语言中继承的功能
package main type innerS struct {
in1 int
in2 int
} type outerS struct {
b int
c float32
int //anonymous field
innerS //anonymous field
} func main() {
outer := new(outerS)
outer.in1 = //outerS.in1 is innerS.in1
outer.in2 = //outerS.in2 is innerS.in2
outer.int = //int is also the anonymous filed name outer2 := outerS{, 6.7, , innerS{, }} //outerS can also be initialized in this format
}
匿名struct里面的filed就变成外面struct的field。
注:在一个struct内,对于每种类型,只能有一个匿名类型的field。
名字冲突问题
由于一个struct里面可以包含多个匿名的不同类型的struct,那当有名字相同的filed时,go怎么处理呢?
1. outer field比inner field优先级更高,也就是外面的会覆盖掉里面的。
2. 如果两个field层级一样
a. 如果这个field名字,没有被用到的话,不会有问题。
b. 如果被用到了,会有编译错误。
[Go语言]从Docker源码学习Go——指针和Structs的更多相关文章
- [Go语言]从Docker源码学习Go——结构和函数的定义
Docker在最近很火,而作为Docker的开发语言-Go也再次被大家提到. 已经使用Docker一段时间了,但是对于源码,尤其是其开发语言Go却一直是一知半解. 最近准备利用空余时间从Docker源 ...
- [Go语言]从Docker源码学习Go——function和method
function和method关系 method是针对某一类型定义的function, function可以单独调用,method必须针对某一类型的实例进行调用 //function 调用方式 pac ...
- [Go语言]从Docker源码学习Go——if语句和map结构
if语句 继续看docker.go文件的main函数 if reexec.Init() { return } go语言的if不需要像其它语言那样必须加括号,而且,可以在判断以前,增加赋值语句 语法 I ...
- [Go语言]从Docker源码学习Go——init()方法和identifier首字母大小写区分
init()方法 如果想在一个go文件里,进行一些初始化的工作,可以把代码放到init()方法中. init()方法先被执行. func init() { // initialization of p ...
- [Go语言]从Docker源码学习Go——main函数
Go程序从main包下的main函数开始执行,当main执行结束后,程序退出. Docker的main函数在 docker/docker/docker.go package main //Import ...
- [Go语言]从Docker源码学习Go——Interfaces
Interface定义: type Namer interface { Method1(param_list) return_type Method2(param_list) return_type ...
- Go语言 context包源码学习
你必须非常努力,才能看起来毫不费力! 微信搜索公众号[ 漫漫Coding路 ],一起From Zero To Hero ! 前言 日常 Go 开发中,Context 包是用的最多的一个了,几乎所有函数 ...
- Docker源码分析(三):Docker Daemon启动
1 前言 Docker诞生以来,便引领了轻量级虚拟化容器领域的技术热潮.在这一潮流下,Google.IBM.Redhat等业界翘楚纷纷加入Docker阵营.虽然目前Docker仍然主要基于Linux平 ...
- Docker源码分析(二):Docker Client创建与命令执行
1. 前言 如今,Docker作为业界领先的轻量级虚拟化容器管理引擎,给全球开发者提供了一种新颖.便捷的软件集成测试与部署之道.在团队开发软件时,Docker可以提供可复用的运行环境.灵活的资源配置. ...
随机推荐
- Linux的定时器
在服务端程序设计中,与时间有关的常见任务有: 获取当前时间,计算时间间隔: 定时操作,比如在预定的时间执行一项任务,或者在一段延时之后执行一项任务. Linux 时间函数 Linux 的计时函数,用于 ...
- CGGeometry Reference
CGRectUnionCGRectUnion接受两个CGRect结构体作为参数并且返回一个能够包含这两个矩形的最小矩形.听起来可能没什么,我相信你也可以用几行代码轻松实现这个功能,不过 CGGeome ...
- 【转】火星坐标、百度坐标、WGS-84坐标相互转换及墨卡托投影坐标转经纬度JavaScript版
原文地址:https://www.cnblogs.com/fwc1994/p/5884115.html 火星坐标 火星坐标是国家测绘局为了国家安全在原始坐标的基础上进行偏移得到的坐标,基本国内的电子地 ...
- Java自带命令详解
1. 背景 给一个系统定位问题的时候,知识.经验是关键基础,数据(运行日志.异常堆栈.GC日志.线程快照[threaddump / javacore文件].堆转储快照[heapdump / hprof ...
- Atitit.遍历图像像素点rgb java attilax总结
Atitit.遍历图像像素点rgb java attilax总结 1. 遍历像素点 1 2. 提取一行 1 3. Rgb分量提取 2 4. 其他读取像素 3 5. --code 5 6. 参考 6 1 ...
- linux上定时备份mysql数据库
定时备份数据库 /usr/sbin/backupmysql timestamp=`date +"%Y-%m-%d-%H-%M-%S"` mysqldump -uroot -p'12 ...
- 如何在openWRT系统上实现双版本
最近由于项目需要,需要在AR9331芯片单板(原来是4MBFlash,后来扩充到16MB Flash)上,实现openwrt双版本机制. 双版本的好处,主要是:在升级版本过程中,如果遇到断电等情况,不 ...
- poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙
/** 题目:poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙 链接:http://poj.org/problem?id=3680 题意:给定n个区间,每个区间(ai,bi ...
- (转载)Android 3.0动画学习笔记
转自http://www.cnblogs.com/angeldevil/archive/2011/12/02/2271096.html.该文章是本人见过关于Android 动画较为优秀的文章,多次查阅 ...
- 微信小程序2 - 扩展Page参数
官方默认的Page初始代码为 var option = { /** * 页面的初始数据 */ data: { }, /** * 生命周期函数--监听页面加载 * */ onLoad: function ...