[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可以提供可复用的运行环境.灵活的资源配置. ...
随机推荐
- 一个可变布局列表,有9种布局item大小,每个item可拖拽切换位置
代码地址如下:http://www.demodashi.com/demo/11271.html 一.准备工作 准备一台安卓设备手机,4.4以上版本 本例子实现,一个可变布局列表,有9种布局item大小 ...
- ios8设置application badge value
在ios8中,直接设置application badge value会出错 [[UIApplication sharedApplication] setApplicationIconBadgeNumb ...
- 基于easyui fom分组插件
本插件适用于表单按属性分组,可以动态设置显示的列数,每一个表单宽度,表单类型,以及对齐.不同panel之间的表单也是对齐的. 效果: 依赖:jquery ,easyui, 实现过程:整个控件一个pan ...
- laravel数据库操作sql语句用Eloquent ORM来构造
现在有查询语句: SELECT users.sNmame, users.iCreateTime, users_ext.iAge, users_ext.sSex FROM users LEFT JOIN ...
- Struts2动作
ActionContext 每一个请求的处理都在一个独立的线程中.每一个线程都有一个ActionContext对象.它包括了ValueStack和HttpServletRequest的东西. Stru ...
- 通过 SysVinit、Systemd 和 Upstart 管理系统自启动进程和服务
管理 Linux 自启动进程 Linux 系统的启动程序包括多个阶段,每个阶段由一个不同的图示块表示.下面的图示简要总结了启动过程以及所有包括的主要组件. Linux 启动过程 当你按下你机器上的电源 ...
- redis命令_INCR
INCR key 将 key 中储存的数字值增一. 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作. 如果值包含错误的类型,或字符串类型的值不能表示为数字,那 ...
- ECMall2.x模板制作入门系列之2(模板标签/语法)
ECMall2.x模板制作入门系列之2(模板标签/语法) 今天给大家带来一个模板语法的教程.希望能为ECMall模板制作者提供一份参考资料.如有问题.建议和意见,欢迎提出. 在ECMall模板中,用& ...
- 简单说一下 servlet的生命周期?
1.servlet有良好的生存期的定义,包括加载和实例化.初始化.处理请求以及服务结束.这个生存期由 javax.servlet.Servlet接口的 init,service和 destroy ...
- vue 过渡状态
vue的过渡系统提供了非常多简单的方法设置进入.离开和列表的动效.那么对于数据元素本身的动效呢,例: 数字和运算 颜色的显示 svg节点的位置 元素的大小和其他的属性 所有的原始数字都被事先存储起来, ...