【问题标题】:How does a pointer to a struct or array value in Go work?Go 中指向结构或数组值的指针如何工作?
【发布时间】:2018-06-25 07:36:25
【问题描述】:

考虑以下 Go 结构:

type Person struct {
    Name    string
    Age     int
    Country string
}

我遇到过无数次如下使用:

p := &Person{"Adam", 33, "Argentina"}

但我看不出指向结构值的意义,我想知道它与:

n := &999 // Error

我的问题是:

  1. 怎么可能指向一个值,即使它是一个结构或数组,而不是像字符串或 int 这样的原始类型?很奇怪,以下内容对我的理解没有帮助:

    fmt.Println(p, &p) // outputs: &{Adam 33 Argentina} 0xc042084018
    
  2. 为什么程序员要通过指针声明结构实例?这样做你能取得什么成就?

【问题讨论】:

    标签: pointers go struct reference


    【解决方案1】:

    &Person{} 是一种语言“构造”,它是规范的一部分:它分配一个 Person 类型的新变量,并为您提供该匿名变量的地址。

    Spec: Composite literals:

    复合文字的Taking the address 生成一个指向唯一variable 的指针,该variable 用文字的值初始化。

    还有:Spec: Variables:

    调用内置函数new获取composite literal 的地址会在运行时为变量分配存储空间

    &999 是语言规范不允许的。地址运算符的可能操作数列在Spec: Address operators:

    操作数必须是可寻址,即变量、指针间接或切片索引操作;或可寻址结构操作数的字段选择器;或可寻址数组的数组索引操作。作为可寻址性要求的一个例外,x 也可以是(可能带括号的)composite literal

    p := Person{} 创建一个新变量p,其类型将为Personp := &Person{} 创建一个类型为*Person 的新变量。

    查看可能的重复:How do I do a literal *int64 in Go?

    当你用fmt包打印值时,它有一定的规则如何打印不同类型的值:

    对于复合对象,使用这些规则以递归方式打印元素,布局如下:

    struct:             {field0 field1 ...}
    array, slice:       [elem0 elem1 ...]
    maps:               map[key1:value1 key2:value2]
    pointer to above:   &{}, &[], &map[]
    

    当您使用fmt.Println() 时,将应用默认的格式化规则,对于*int 类型的值是%p 动词,它将以十六进制格式打印内存地址,但对于指向结构的指针它打印前面带有& 符号(&{})的结构值。您可以在相关问题中了解更多信息:Difference between golang pointers

    如果要打印指向的值,取消引用指针并传递指向的值,例如:

    var p = new(int)
    *p = 12
    fmt.Println(*p) // Prints 12
    

    关于为什么要创建指向值(而不是值)的指针,请参阅这些相关问题:

    Pointers vs. values in parameters and return values

    Why should constructor of Go return address?

    Go, X does not implement Y (... method has a pointer receiver)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-01
      • 1970-01-01
      • 2017-06-03
      • 2019-07-06
      • 2016-10-19
      • 1970-01-01
      • 2012-12-07
      相关资源
      最近更新 更多