Java 只有引用,Go 的指针 * 到底是什么?内存模型一次讲透
本文为《Java工程师转Go实战》连载第 4 篇 / 共 20 篇上一篇基础语法一天速通下一篇没有 class 和继承Go 怎么写业务类比开场Java 里你很少写指针但每天都在用对象变量本质是引用的拷贝。UseranewUser(张三);Userba;b.setName(李四);// a.getName() 也变成 李四Go 把这件事说得更直白你可以选择传值还是传指针而且语法里直接有*和。一、三个符号搞懂 80%符号读法含义x取地址得到 x 的指针*p解引用通过指针访问指向的值*T类型「指向 T 的指针」类型x:42p:x// p 的类型是 *intfmt.Println(*p)// 42*p100fmt.Println(x)// 100二、Java 引用 vs Go 指针Java 对象Go 值类型Go 指针赋值引用拷贝整份拷贝地址拷贝修改影响原对象是否是空null零值nil谁管内存GC栈或堆编译器决定同左typeCounterstruct{Nint}funcaddValue(c Counter){c.N}// 不改外面funcaddPtr(c*Counter){c.N}// 改外面funcmain(){c:Counter{N:0}addValue(c)fmt.Println(c.N)// 0addPtr(c)fmt.Println(c.N)// 1}三、什么时候用指针场景建议方法要修改 receiver 字段指针接收者func (u *User)结构体很大指针避免拷贝需要表示「不存在」*User可为 nil小结构体、只读值接收者即可Java 对照指针接收者 ≈ 在方法里改this的字段值接收者 ≈ 改的是一个副本。四、new 和 makeJava 人必混淆// new分配内存返回指针置零值p:new(int)// *int值为 0// make只用于 slice、map、channel返回已初始化的引用类型s:make([]int,0,10)m:make(map[string]int)ch:make(chanint)Java 里new ArrayList()一个概念搞定Go 把slice/map/chan 的内部结构初始化单独拆给make。五、逃逸分析栈还是堆Java 程序员关心 JVM 堆栈Go 程序员也要关心但多数时候编译器帮你决定。funcfoo()*int{x:42returnx// x 逃逸到堆上——否则函数返回后地址失效}查看逃逸go build-gcflags-m./...面试常考不是说有就一定在堆上逃逸分析才是依据。六、nil 指针陷阱varu*Usernil// u.Name // panic: nil pointer dereferenceifu!nil{fmt.Println(u.Name)}和 JavaNullPointerException一样先判空再解引用。 面试追问Go 有引用类型吗slice、map、channel 是引用类型内部含指针赋值后共享底层数据但和 C 引用不同。值传递还是引用传递Go 永远是值传递。传指针时拷贝的是指针值地址所以能改指向的对象。为什么 slice 改元素会影响原 sliceslice 头是 {指针, len, cap}赋值拷贝的是 header底层数组共享。 一句话总结Java 隐式给你引用Go 显式让你选值拷贝还是指针——搞懂、*和接收者就搞懂了 Go 一半的「对象」行为。建议标签Golang指针Java内存模型面试