5

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

3 Answers 3

2

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)
}
Sign up to request clarification or add additional context in comments.

1 Comment

After seeing you simplified example, it is more clear to me now and I think you answer is reasonable. Your "never save off a reference" is what they called non-addressable in the book, and I guess that's why you can't access the field without saving the new struct as a variable first.
2

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

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.