Golang指针如何修改变量值_通过指针操作变量技巧

必须用 解引用才能修改原变量值,指针本身只是地址,不加 操作的是指针变量自身;传指针进函数需用 *p 修改目标值,nil 指针解引用会 panic,须判空;结构体嵌套指针字段需逐层检查并初始化;new(T) 仅得零值指针,&T{} 支持字段初始化;返回局部变量地址安全,因逃逸分析自动移至堆。

golang指针如何修改变量值_通过指针操作变量技巧

* 解引用才能改原变量的值

Go 里指针本身只是个地址值,不加 * 就是在操作指针变量自己(比如赋新地址),不是在改它指向的值。常见错误是传指针进去却忘了 *,结果函数里看似“改了”,实际原变量毫发无伤。

实操要点:

  • 声明指针用 &,修改目标值必须用 * 前缀
  • 函数参数接收 *int,内部要写 *p = 42 才能改调用方的 int
  • nil 指针解引用会 panic,操作前建议判空(尤其从 map 或函数返回获取的指针)
func increment(p *int) {
    if p != nil { // 防 panic
        *p++
    }
}
x := 10
increment(&x)
// x 现在是 11

结构体指针字段赋值要注意是否已初始化

结构体指针字段(如 type User struct{ Profile *Profile })默认是 nil。直接写 u.Profile.Name = "Alice" 会 panic:assignment to entry in nil map / invalid memory address。

正确做法:

立即学习go语言免费学习笔记(深入)”;

问小白

问小白

免费使用DeepSeek满血版

下载

  • 先检查 u.Profile != nil,再赋值
  • 或提前初始化:u.Profile = &Profile{}
  • 如果字段是嵌套指针(如 *map[string]int),需逐层判空 + 初始化
type Config struct {
    DB *DBConfig
}
c := &Config{}
if c.DB == nil {
    c.DB = &DBConfig{Host: "localhost"}
}
c.DB.Port = 5432 // 安全

new()&T{} 初始化指针的区别

两者都返回指向新分配零值的指针,但语义和适用场景不同:

  • new(T) 只能创建零值,返回 *T,适合简单类型或明确需要零值的场景
  • &T{Field: val} 支持字段初始化,更常用,尤其结构体
  • 切片、map、channel 不能用 new() 初始化(它们本身是引用类型,new([]int) 返回的是 *[]int,不是你想要的可 append 的切片)
// ✅ 正确
p1 := new(int)      // *int,值为 0
p2 := &User{Name: "Tom"} // *User,Name 已赋值

// ❌ 错误用法
s := new([]string)  // 得到 **[]string,不是能 append 的切片
// 应该用:
s := make([]string, 0)

函数返回局部变量地址是安全的

Go 编译器会自动做逃逸分析,把本该分配在上的变量提升到堆上,所以返回局部变量地址不会导致悬垂指针。这点和 C/C++ 完全不同,不必手动 malloc 或担心生命周期。

但要注意:

  • 返回局部变量地址是安全的,但返回局部数组/切片的元素地址可能有问题(因为底层数组可能被回收)
  • 若函数内创建大对象并返回其指针,可能增加 GC 压力,需结合性能权衡
  • 不要依赖“栈分配”做性能优化——Go 不保证也不暴露栈/堆细节
func getCounter() *int {
    x := 0 // x 会被自动移到堆上
    return &x
}
p := getCounter()
*p = 100 // 完全合法

真正容易出错的地方不在语法,而在忘记解引用、忽略 nil 检查、或误以为返回局部变量地址是危险操作——Go 把这些底层细节藏好了,你只需盯紧 *& 的配对,以及每个指针值是否真实指向有效内存。

https://www.php.cn/faq/2011983.html

发表回复

Your email address will not be published. Required fields are marked *