我的函数 returns 一个结构;为什么编译器不允许分配给该结果值的字段?

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

在golang中,如果我在一个函数中return一个struct类型,编译出错,我必须使用struct的指针作为return类型来直接通过函数调用。这是为什么? foo() return 不是 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
}

在 Go 中,variable 是可寻址的,即可以获取地址的值。如果左侧可寻址,则赋值有效。

bar().Salary = 1 是合法的,因为

  1. bar().Salary其实是(*bar()).Salary;
  2. 的语法糖
  3. *bar() 是可寻址的,因为它是一个指针间接寻址;
  4. 可寻址结构的字段(例如Salary)本身是可寻址的

相比之下,foo().Salary = 1 是非法的,因为 foo() returns 是一个值,但它 不是 变量,也不是指针间接寻址;无法获得 foo() 的地址。这就解释了为什么该语句被编译器拒绝。注意引入一个中间变量就解决了你的问题:

// type and function declarations omitted

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

foo() returns 一个 'value' 结构类型,我们不能将任何东西赋值给一个值。 而 bar() returns 一个指向变量的指针。我们可以使用这个指针给这个变量赋不同的值

此错误本质上与结构无关,但与为值赋值有关。考虑以下示例:


func retint() int{
    var a int=5
    return a
}

func retintp() *int{
    var a int=5
    return &a
}
func main(){
    print("hello")
    *retintp()=10   // this is valid as we can store 10 to address pointed by a
    retint()=10     // this gives error. as we can not assign 10 to 5

}

这里retint() returns一个值(5)。除了 retintp() returns 变量 a 的地址,我们不能给 5 赋值。我们可以用这个地址给它赋值

bar().Salary = 1 

Returns一个指针,我们正在写入指针指向的对象

foo().Salary = 1

foo() returns 一个临时对象,由于我们没有将它存储在任何地方,如果不分配给变量,临时对象将会丢失。因此 go 编译器抱怨

以下将起作用

f = foo()
f.Salary = 1