zoukankan      html  css  js  c++  java
  • [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 := 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. 如果被用到了,会有编译错误。

  • 相关阅读:
    Node 12 值得关注的新特性
    vue实现PC端调用摄像头拍照人脸录入、移动端调用手机前置摄像头人脸录入、及图片旋转矫正、压缩上传base64格式/文件格式
    解决Vuex刷新页面数据丢失问题 ---- vuex-persistedstate持久化数据
    博客搬迁到 gitHub + hexo 去了, 博客园以后比较少更新
    Jenkins结合shell脚本实现(gitLab/gitHub)前端项目自动打包部署服务器
    GET 和 POST 的区别 以及为什么 GET请求 比 POST请求 更快
    Git常用命令及使用,GitLab/GitHub初探,Git/Svn区别
    pc端结合canvas实现简单签名功能
    N的阶乘末尾0的个数和其二进制表示中最后位1的位置
    实现一个动态存储分配
  • 原文地址:https://www.cnblogs.com/lemonbar/p/3928357.html
Copyright © 2011-2022 走看看