指针/非指针类型的结构字段赋值差异

huangapple go评论64阅读模式
英文:

struct field assignment difference of pointer/non-pointer type

问题

在《The Go Programming Language》的第4.4节(结构体)中,有一段代码摘录:

var dilbert Employee
func EmployeeByID(id int) *Employee { /* ... */ }
id := dilbert.ID
EmployeeByID(id).salary = 0

并附有以下备注:

如果将EmployeeByID的结果类型从*Employee更改为Employee,那么赋值语句将无法编译,因为其左侧不会识别为变量。

我不明白为什么将EmployeeByID的结果类型更改为Employee会导致左侧不识别为变量。

英文:

In section 4.4 (Structs) of The Go Programming Language, there is a code excerpt:

var dilbert Employee
func EmployeeByID(id int) *Employee { /* ... */ }
id := dilbert.ID
EmployeeByID(id).salary = 0

with the remark

> If the result type of EmployeeByID were changed to Employee instead of *Employee, the assignment statement would not compile since its left-hand side would not identify a variable.

I don't understand why changing the result type of EmployeeByID to Employee would cause LHS not identify a variable.

答案1

得分: 2

这个简化的示例演示了问题:

package main

type t struct {
    int
}

func newT() *t { return &t{} }
//func newT() t { return t{} }

func main() {
    newT().int = 0
}

我猜测,如果你使用不返回指针的newT版本,并且从不保存newT()结果的引用,那么设置其int字段的值就没有任何意义。这类似于设置一个未使用的变量。

如果你使用非指针版本的newT,但是有类似以下的代码:

x := newT()
x.int = 0

那么就没问题。

另外,使用上面的指针版本的newT也是可以的,因为它可能返回你之前已经定义的某些状态,参见示例

package main

type t struct {
    int
}

var dilbert = &t{3}

func newT() *t { return dilbert }

//func newT() t { return t{} }

func main() {
    println(dilbert.int)
    newT().int = 0
    println(dilbert.int)
}
英文:

This simplified example demonstrates the issue:

package main

type t struct {
    int
}

func newT() *t { return &t{} }
//func newT() t { return t{} }

func main() {
    newT().int = 0
}

My guess is that if you use the version of newT that does not return a pointer, and never save off a reference to the result of newT(), then setting the value of its int field can never meaningfully do anything. It's similar to setting an unused variable.

If instead you the non-pointer version of newT but you have something like:

x := newT()
x.int = 0

Then you'd be fine.

Alternatively, using the pointer version of newT above is fine, because it could be returning some state you already had defined previously, see example:

package main

type t struct {
    int
}

var dilbert = &t{3}

func newT() *t { return dilbert }

//func newT() t { return t{} }

func main() {
	println(dilbert.int)
	newT().int = 0
    println(dilbert.int)
}

答案2

得分: 2

我已经研究了这个问题,我认为如果你将*Employee更改为Employee,那么EmployeeByID(id)将成为一个不可寻址的值,因为它没有被分配给一个变量。如果你像下面这样给它分配一个变量,那就没问题了:

e1 := EmployeeByID(id)
e1.Salary = 0
英文:

I have researched on this topic, and I think the problem if you change to Employee instead of *Employee, then EmployeeByID(id) will be a unaddressable value since it is not assigned to a variable. It is OK if you assign it a variable like below:

e1 := EmployeeByID(id)
e1.Salary = 0

答案3

得分: 1

func EmployeeByID(id int) Employee { / ... */ }
这个函数返回一个指向Employee变量的指针。

func EmployeeByID(id int) Employee { /* ... */ }
这个函数返回从Employee变量复制的。在使用之前,你需要将其赋值给一个变量。

英文:
func EmployeeByID(id int) *Employee { /* ... */ }

This return a pointer to an Employee variable.

func EmployeeByID(id int) Employee { /* ... */ }

This returns a value copied from an Employee variable. You need to assign it to a variable before using it.

huangapple
  • 本文由 发表于 2015年11月22日 11:06:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/33851189.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定