Go 指针详解:Golang 初学者如何理解指针和内存传递

为什么 Go 指针是很多初学者的难点

在学习 Go 的过程中,指针通常是一个绕不开的话题。很多人第一次接触指针时,会觉得它很抽象,尤其是看到 &* 这些符号时,容易一下子把自己绕进去。

其实 Go 的指针已经比 C 语言简单很多。Go 不支持指针运算,也不鼓励开发者做太底层、太危险的操作。它保留指针,主要是为了提高效率,以及让某些数据修改能够直接作用到原对象上。

所以学习 Go 指针,不需要把它想得过于复杂。核心只要理解:指针保存的是变量的地址,通过地址可以间接访问或修改原值。


Go 中怎么定义指针

先看一个简单例子:

package main

import "fmt"

func main() {
    a := 10
    p := &a

    fmt.Println(a)
    fmt.Println(p)
}

这里:

  • a 是一个普通整数变量
  • &a 表示获取变量 a 的地址
  • p 就是一个指针变量,保存了 a 的内存地址

所以,p 不是 a 的值,而是指向 a 的位置。


Go 中的 & 和 * 分别是什么意思

这是最基础也最容易混的地方。

& 取地址

a := 10
p := &a

这里的 &a 表示“取出变量 a 的地址”。

* 解引用

fmt.Println(*p)

这里的 *p 表示“根据指针 p 找到它指向的值”。

所以可以简单记:

  • &:拿地址
  • *:取地址对应的值

Go 指针能修改原变量吗

可以,这也是指针最重要的用途之一。

a := 10
p := &a

*p = 20

fmt.Println(a) // 20

因为 p 指向的是 a 的地址,所以通过 *p 修改的,本质上就是原变量 a 的内容。

这也是为什么在函数中,如果你想修改外部变量的值,通常就要传入指针。


Go 函数参数为什么有时要传指针

Go 默认是值传递,也就是说,函数拿到的是参数的一份副本。

例如:

func update(x int) {
    x = 100
}

调用后,原变量不会变:

a := 10
update(a)
fmt.Println(a) // 10

因为 update 改的是副本,不是原值。

如果想直接修改原变量,就可以传指针:

func update(x *int) {
    *x = 100
}

调用:

a := 10
update(&a)
fmt.Println(a) // 100

这时修改就会生效。


Go 结构体为什么经常配合指针使用

在实际项目中,结构体通常会比较大,如果每次传参都复制一整份,会有额外开销。因此很多情况下,结构体会通过指针传递。

例如:

type User struct {
    Name string
    Age  int
}

func changeName(u *User) {
    u.Name = "Tom"
}

调用:

user := User{Name: "Alice", Age: 20}
changeName(&user)
fmt.Println(user.Name) // Tom

这里通过指针传递,不仅节省拷贝成本,也能直接修改原结构体。

Go 在访问结构体指针字段时还做了语法简化,虽然 u 是指针,但可以直接写 u.Name,不需要写成 (*u).Name,这让代码可读性好了很多。


Go 指针有哪些常见使用场景

Go 中的指针最常出现在这些地方:

  • 需要修改函数外部变量
  • 传递较大的结构体对象,减少拷贝
  • 为结构体定义指针接收者方法
  • 与某些底层库或资源对象交互
  • 表示“可为空”的状态

尤其是在方法定义中,指针接收者非常常见。

例如:

func (u *User) GrowUp() {
    u.Age++
}

这样方法就能修改结构体原值。


Go 指针和引用是一回事吗

严格来说,不完全一样。Go 本身并没有像某些语言那样明确提供“引用”这个语法概念,但切片、map、channel 这类类型在使用时,确实常常表现出类似引用的效果。

而指针则更直接,它明确表示“这个变量里存的是地址”。

所以学习时不要把所有“能改原值”的东西都笼统叫成引用,最好区分清楚:
指针是地址;
切片、map、channel 是带有引用语义特征的数据类型。


Go 指针学习中的常见误区

第一,见到 * 就紧张。
其实只要分清“定义指针”和“解引用”两个场景,就不会太乱。

第二,不清楚什么时候该传值,什么时候该传指针。
一般来说,小而简单的数据可以传值;需要修改原值或避免大对象拷贝时,优先考虑传指针。

第三,以为 Go 指针和 C 一样危险复杂。
实际上 Go 已经去掉了很多容易出问题的底层指针操作,使用起来安全得多。

第四,对空指针没有防范。
如果一个指针没有初始化就直接解引用,会导致运行时错误。


总结

Go 指针的核心并不复杂,本质就是通过地址访问和修改数据。它存在的主要意义,一是减少数据拷贝,提高效率;二是让函数或方法能够直接修改原对象。

对于初学者来说,学习 Go 指针最重要的不是死记符号,而是理解它解决的问题:什么时候需要直接改原值,什么时候不想复制大对象,只要围绕这些实际需求去理解,指针就不会显得那么抽象。

posted @ 2026-03-15 15:55  空之匣  阅读(2)  评论(0)    收藏  举报