Ryan
Ryan

Reputation: 77

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.

Upvotes: 5

Views: 597

Answers (3)

Song
Song

Reputation: 126

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.

Upvotes: 1

xuefeng huang
xuefeng huang

Reputation: 137

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

Upvotes: 2

Amit Kumar Gupta
Amit Kumar Gupta

Reputation: 18587

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

Upvotes: 2

Related Questions