在 Go 中,只有可寻址的变量才能作为赋值操作的左值;函数返回的结构体值(非指针)是临时、不可寻址的,因此无法直接对其字段赋值,而返回指针则可寻址并支持字段修改。

在 Go 中,只有可寻址的变量才能作为赋值操作的左值;函数返回的结构体值(非指针)是临时、不可寻址的,因此无法直接对其字段赋值,而返回指针则可寻址并支持字段修改。

Go 语言里有一条挺硬的规则:赋值语句的左边,必须是一个在内存里“有固定位置”的东西,也就是能通过 &x 拿到地址的变量。这不是随便定的,而是为了保证每次赋值都有实实在在的副作用——你要是能随便改一个临时值,那改完就丢,谁也没法知道,毫无意义。

来,看个简单例子就明白了:

package main

type Employee struct {
    ID     int
    Salary float64
}

func EmployeeByID(id int) *Employee {
    return &Employee{ID: id, Salary: 5000.0}
}

func EmployeeByIDValue(id int) Employee {
    return Employee{ID: id, Salary: 5000.0}
}

func main() {
    id := 123

    // ✅ 合法:*Employee 是可寻址的(指向堆/栈上的实际结构体)
    EmployeeByID(id).Salary = 0 // 修改生效,影响底层对象

    // ❌ 编译错误:Employee 值是临时的、不可寻址的
    // EmployeeByIDValue(id).Salary = 0 // compile error: cannot assign to EmployeeByIDValue(id).Salary

    // ✅ 合法(但效果不同):先绑定到变量,再赋值
    emp := EmployeeByIDValue(id)
    emp.Salary = 0 // 修改的是 emp 的副本,原返回值已丢弃,无外部影响
}

这里的关键就两点:

⚠️ 有几点需要特别提醒:

总结一下:Go 通过强制“可寻址性”这个机制,把内存安全和语义清晰都照顾到了——只有真正持有状态的对象(变量、切片元素、解引用后的指针等等)才允许你对它的字段进行赋值。理解了这一点,写 Go 代码的时候就能避免很多莫名其妙的错误,也更容易写出符合语言惯用法的代码。

本文转载于:https://www.php.cn/faq/2332335.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。