• [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. 如果被用到了,会有编译错误。

  • 相关阅读:
    HDU 1058 Humble Numbers
    HDU 1160 FatMouse's Speed
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1003 Max Sum
    HDU 1297 Children’s Queue
    UVA1584环状序列 Circular Sequence
    UVA442 矩阵链乘 Matrix Chain Multiplication
    DjangoModels修改后出现You are trying to add a non-nullable field 'download' to book without a default; we can't do that (the database needs something to populate existing rows). Please select a fix:
    opencv做的简单播放器
    c++文件流输入输出
  • 原文地址:https://www.cnblogs.com/lemonbar/p/3928357.html
Copyright © 2020-2023  润新知