go指针 引用传递

是的,Go语言的值传递和指针传递完全由开发者自己控制,这是Go语言的一个重要特点。

核心原则

Go语言始终是值传递,但你可以选择传递什么:

详细对比

1. 函数参数 - 你自己决定

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)   // 你选择传指针

2. 方法接收者(Receiver) - 你自己决定

// 值接收者 - 方法内修改不影响原对象
func (u User) SetAgeByValue(age int) {
    u.Age = age  // 无效,只修改了副本
}

// 指针接收者 - 方法内修改会影响原对象
func (u *User) SetAgeByPointer(age int) {
    u.Age = age  // 有效,修改了原对象
}

3. 变量赋值 - 你自己决定

// 值赋值
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
}

与其他语言对比