Go 语言中的值类型和指针类型区别对比分析
作者:半桶水专家
在Go语言中,值类型(如int、struct)存储实际数据,而指针类型(如*int、*struct)存储数据的内存地址,值类型是按值传递的,修改不会影响原变量,本文给大家介绍Go 语言中的值类型和指针类型,感兴趣的朋友跟随小编一起看看吧
在 Go 语言中,变量的类型可以是值类型(Value Type)或指针类型(Pointer Type)。它们的核心区别在于:存储的内容不同、内存地址的变化不同、函数传参的行为不同。
下面我从本质 + 内存模型 + 例子 + 什么时候用指针 来完整解释。
✅ 一、值类型 vs 指针类型 — 本质区别
| 特性 | 值类型 | 指针类型 |
|---|---|---|
| 存储内容 | 实际数据 | 数据的内存地址(指向某个值) |
| 赋值时 | 拷贝整份数据 | 拷贝地址(两个指针指向同一块内存) |
| 改动是否影响原变量 | ❌ 不影响 | ✔ 会影响 |
| 空值 | 无法为 nil | 可以为 nil |
| 内存分配 | 栈为主 | 指向堆或栈都可能 |
✅ 二、本质理解:变量保存的是什么?
✔ 值类型(int、float、struct、array 等)
变量里保存的是“真实的数据”。
a := 10 b := a // b 拷贝一份 10 b = 20 fmt.Println(a) // 10 (不会受到影响)
值类型总是复制一份独立的数据。
✔ 指针类型(*int、*struct、*MyType)
变量里保存的是“另一个变量的地址”。
a := 10 b := &a // b 保存 a 的地址 *b = 20 fmt.Println(a) // 20 (a 被修改)
指针类型意味着多个变量指向同一块内存,因此修改一个会影响另一个。
✅ 三、内存示意图(最直观)
✔ 值类型
a (10) b (10) ← 拷贝出的新数据
✔ 指针类型
a (10) b (&a) → 指向 a 的内存地址
✅ 四、函数传参时的区别(非常重要)
值类型:传值,拷贝一份
func add(x int) {
x++
}
a := 10
add(a)
fmt.Println(a) // 10(没有改变)指针类型:传地址,修改原变量
func add(x *int) {
(*x)++
}
a := 10
add(&a)
fmt.Println(a) // 11(被改变了)✅ 五、结构体特别重要:值类型默认复制!
type User struct {
Name string
}
func change(u User) {
u.Name = "Tom"
}
func main() {
user := User{Name: "Sam"}
change(user)
fmt.Println(user.Name) // Sam(没变)
}改用指针就会改变原数据:
func change(u *User) {
u.Name = "Tom"
}
change(&user)
fmt.Println(user.Name) // Tom✅ 六、什么时候应该使用指针?
✔ 1. 需要修改函数外的变量
修改状态、计数器、累加器等。
✔ 2. struct 较大,避免复制(性能)
Go 的结构体可能很大,复制成本高:
func process(u *LargeStruct) { ... }✔ 3. 实现方法的“接收者”为指针(避免复制)
很多类型的方法必须用指针接收器:
func (u *User) SetName(name string) {
u.Name = name
}✔ 4. 需要表示 nil(值不存在)
var p *User = nil
值类型永远不能为 nil。
✅ 七、一句话总结
- 值类型保存真实值,赋值会复制,不会影响彼此。
- 指针类型保存地址,赋值只复制地址,多个变量共享底层数据。
- 指针多用于需要改变原数据、避免拷贝大结构体、或表示 nil 的场景。
到此这篇关于Go 语言中的值类型和指针类型的文章就介绍到这了,更多相关go语言值类型和指针类型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
