我的函数 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
是合法的,因为
bar().Salary
其实是(*bar()).Salary
; 的语法糖
*bar()
是可寻址的,因为它是一个指针间接寻址;
- 可寻址结构的字段(例如
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
在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
是合法的,因为
bar().Salary
其实是(*bar()).Salary
; 的语法糖
*bar()
是可寻址的,因为它是一个指针间接寻址;- 可寻址结构的字段(例如
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