是的,Go语言的值传递和指针传递完全由开发者自己控制,这是Go语言的一个重要特点。
Go语言始终是值传递,但你可以选择传递什么:
type User struct {
Name string
Age int
}
// 值传递 - 复制整个结构体
func updateUserByValue(u User) {
u.Age = 30 // 不会影响原始数据
}
// 指针传递 - 传递地址
func updateUserByPointer(u *User) {
u.Age = 30 // 会修改原始数据
}
// 使用
user := User{Name: "张三", Age: 18}
updateUserByValue(user) // 你选择传值
updateUserByPointer(&user) // 你选择传指针
// 值接收者 - 方法内修改不影响原对象
func (u User) SetAgeByValue(age int) {
u.Age = age // 无效,只修改了副本
}
// 指针接收者 - 方法内修改会影响原对象
func (u *User) SetAgeByPointer(age int) {
u.Age = age // 有效,修改了原对象
}
// 值赋值
user1 := User{Name: "张三", Age: 18}
user2 := user1 // 复制了一份,user2 和 user1 独立
// 指针赋值
user3 := &User{Name: "李四", Age: 20}
user4 := user3 // user4 和 user3 指向同一个对象
// 1. 小型结构体(几个基本类型字段)
type Point struct {
X, Y int
}
func distance(p Point) float64 { ... }
// 2. 不需要修改原数据
func printUser(u User) {
fmt.Println(u.Name)
}
// 3. 基本类型
func add(a, b int) int {
return a + b
}
// 1. 大型结构体(避免复制开销)
type LargeStruct struct {
Data [10000]int
}
func process(ls *LargeStruct) { ... }
// 2. 需要修改原数据
func (u *User) UpdateAge(age int) {
u.Age = age
}
// 3. 方法接收者(惯例:统一用指针)
func (um *userManager) deliveryMessage(...) error { ... }
// 4. 实现接口时需要修改状态
type Writer interface {
Write([]byte) error
}