在go语言中,如果给结构体的临时变量的字段赋值,会出现编译错误。
type Employee struct {
ID int
Name, Address string
}
func EmployeeById(id int) *Employee {
return &Employee{ID: id, Name: "hello", Address: "beijing"}
}
func EmployeeById2(id int) Employee {
return Employee{ID: id, Name: "hello", Address: "beijing"}
}
func main() {
EmployeeById(0).ID = 11
// 编译错误
EmployeeById2(0).ID = 10
// 与上一句的编译错误属于同一个类型。声明了hello之后没有访问。
hello := 0
// 下面这段没有问题
employee := EmployeeById2(0)
employee.ID = 2
fmt.Println(employee) //打印出的ID是2
}
为什么会出现编译错误?
对于EmployeeById返回的指针临时变量的字段赋值不会有编译错误,是因为这个赋值是有意义的。因为这个赋值语句更新了EmployeeById返回的指针所指向的对象。
但是EmployeeById2返回的是一个结构体的副本。更新副本的字段,只会更新该副本对象;而这是一个临时变量,之后再也无法访问,因此GO编译器认为是没有意义的操作,报编译错误。与后面一句hello := 0
(hello被声明了,但是没有被访问)的编译错误一样。
上面的解释可能不太对。
看下编译器的提示:
EmployeeById2(0).ID = 10
这句的主要问题是,赋值语句的左侧是不可寻址(addressable)的,或者映射索引表达式(map index expression)。所谓可寻址的,包括变量、结构体字段、数组元素。在这里,虽然EmployeeById2(0).ID是一个结构体字段,但是该结构体不是可寻址的,因为EmployeeById2(0)是一个临时变量,无法再访问到EmployeeById2(0);所谓映射索引表达式,就是go中的map类型。