设为首页 收藏本站
查看: 1586|回复: 0

[经验分享] [Go语言]从Docker源码学习Go——指针和Structs

[复制链接]

尚未签到

发表于 2015-4-17 10:53:03 | 显示全部楼层 |阅读模式
  这两天在看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 := 1
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 = 3 //outerS.in1 is innerS.in1
outer.in2 = 4 //outerS.in2 is innerS.in2
outer.int = 5 //int is also the anonymous filed name

outer2 := outerS{5, 6.7, 20, innerS{3, 4}} //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. 如果被用到了,会有编译错误。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-58104-1-1.html 上篇帖子: ANDROID和DOCKER的一致架构设计(2):包装通信协议 下篇帖子: docker源码打包RPM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表