为什么取消引用地址会在 golang 中产生“无效的间接”错误?

问题描述

type person struct{
  Name string
  Age int
}

// parameters : (pointer to person struct),which is basically address of person object
func printPerson(p *person) {

  // when we add '*' to a address,then it becomes dereferencing,Hence 
  // I read "*p.Name" as "person object dot Name" and i expect it to give value,// I get this error:
  // ./prog.go:20:15: invalid indirect of p.Name (type string)
  // ./prog.go:20:24: invalid indirect of p.Age (type int)
  fmt.Println(*p.Name,*p.Age) // does not works,ERROR THROWN

  // But this works perfectly
  // I read it as "person address dot name and person address dot age"
  // for me it does not make sense when we say "address dot field name",// shouldn't it be "object dot field name ? "
  fmt.Println(p.Name,p.Age)
}
func main() {
  p := person{"foobar",23}
  printPerson(&p) // we are sending address to the method
}

为什么我们不能执行解引用的对象点域名称而不是地址点域名称?请阅读代码注释以获取问题解释,我在这里遗漏了什么?

解决方法

p.Namep.Age 按原样工作,因为如果 p 是指向结构的指针,则 p.Name(*p).Name 的简写。引用自 Spec: Selectors:

在表达式 x.f [...] 中,如果 x 的类型是定义的指针类型并且 (*x).f 是表示字段(但不是方法)的有效选择器表达式,x.f(*x).f 的简写。

鉴于此,*p.Name 不会尝试取消引用 p 并引用 Name 字段,而是尝试取消引用 p.Name 字段,该字段不是指针。

如果您使用括号对间接寻址进行分组,它会起作用:

fmt.Println((*p).Name,(*p).Age)

但同样,由于这种形式非常频繁,Spec 允许您省略指针间接寻址,而只需编写 p.Name

,

在 Go 中,& 运算符用作指向变量的指针并将其地址保存在内存中。 * 可用于“取消引用”此类指针。取消引用指针可以让我们访问指针指向的值。

在您的示例中,当您的函数收到参数 &p(指向变量 p 的指针)时,您可以直接更改其值,因为结构的成员 nameage 'person' 不是指针 (*T)。

如果您要将 struct person 的成员更改为指针类型(如下例所示),它将打印到控制台:指针值(内存地址)和 var { 的值他们指向的 {1}} 和 foobar

age