简体   繁体   中英

struct field assignment difference of pointer/non-pointer type

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.

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)
}

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
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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM