My function returns a struct; why is assignment to a field of that result value disallowed by the compiler?

Issue

In golang, if I return a struct type in a function, I got compilation error, I have to use the pointer of struct as the return type to achieve member access directly via the function call. Why is that? Doesn’t foo() return a temporary variable of type Employee?

package main


type Employee struct {
ID int
Name string
Address string
Position string
Salary int
ManagerID int
}
var dilbert Employee


func foo() Employee {
    employee := Employee{}
    return employee
}

func bar() *Employee {
    employee := Employee{}
    return &employee
}

func main() {
    dilbert.Salary = 1
    var b = foo()
    b.Salary = 1

    bar().Salary = 1    // this is good
    foo().Salary = 1    // this line has the compilation error cannot assign to foo().Salary
}

Solution

In Go, a variable is addressable, i.e. a value of which you can obtain the address. Assignments are valid if the left-hand side is addressable.

bar().Salary = 1 is legal because

  1. bar().Salary is actually syntactic sugar for (*bar()).Salary;
  2. *bar() is addressable because it’s a pointer indirection;
  3. fields (e.g. Salary) of addressable structs are themselves addressable

By contrast, foo().Salary = 1 is illegal because foo() returns a value, but it is not a variable nor a pointer indirection; there is no way of obtaining foo()‘s address. That explains why that statement is rejected by the compiler. Note that introducing an intermediate variable solves your problem:

// type and function declarations omitted

func main() {
    f := foo()
    f.Salary = 1 // compiles fine
}

Answered By – jub0bs

Answer Checked By – Marilyn (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.