查看: 50|回复: 0

Go 语言中的值类型和指针类型区别对比分析

[复制链接]

0

主题

0

回帖

0

积分

积极分子

金币
0
阅读权限
220
精华
0
威望
0
贡献
0
在线时间
0 小时
注册时间
2008-10-24
发表于 2025-11-21 09:34:13 | 显示全部楼层 |阅读模式

在 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 的场景。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

相关侵权、举报、投诉及建议等,请发 E-mail:qiongdian@foxmail.com

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部