一句话先总结

  • 指针:存的是地址,可以指向任意类型的内存地址,你可以让指针指向别的地方。

  • 引用类型:内部也存了地址(底层有指针),但用起来像普通变量,你无法让它“改指向”。

具体区别(多维度对比)

维度 指针(*T) 引用类型(slice/map/channel)
本质 存的是内存地址,就是一个数字 是一个结构体/内部包含指针字段
能否修改指向 可以 p = &otherVar 不能,它直接就是“指向底层数据”本身
创建方式 new(int) 或 &var make([]int, 0) 或字面量
零值 nil(不能直接解引用) nil(但部分操作可用,如len,append)
解引用/取值 需要 *p 直接使用,如 slice[0],map[key]
函数传参效果 传的是地址拷贝,能改原值 传的是内部结构体的拷贝,也能改底层数据

详细解释 + 举例

1. 指针:明确的“地址值”

指针就像一个门牌号,你可以把这个号码抄给别人,别人按号码能找到你家。

// 指针示例
a := 10         // 一个房间,里面放着10
p := &a         // p是房间的门牌号

fmt.Println(*p) // 10, *p 是“顺着门牌号找到里面的东西”

*p = 20         // 通过门牌号改房间里的值
fmt.Println(a)  // 20 (原变量a被改了)

// 指针可以改变指向
b := 30
p = &b          // p现在指向b了
fmt.Println(*p) // 30

函数传参例子:

func changeByPointer(num *int) {
    *num = 100  // 改的是原来的变量
}

func main() {
    x := 5
    changeByPointer(&x)
    fmt.Println(x) // 100 (原来的x被改了)
}

2. 引用类型:伪装成普通值的“指针代理”

引用类型(slice/map/channel)内部已经包含了指针,你不需要*&,它用起来就像普通变量,但传递时能共享内部数据。

Slice 举例:

s := []int{1, 2, 3}  // s内部有指针指向数组{1,2,3}

// 函数传slice
func changeSlice(s []int) {
    s[0] = 100  // ✅ 能改原slice底层数组(类似指针效果)
}

func main() {
    s := []int{1, 2, 3}
    changeSlice(s)
    fmt.Println(s) // [100 2 3] (元素被改了)
    
    // ❌ 但是你不能让外面的s指向一个新slice
    // 除非用指针的指针 *[]int
}

但是注意: 引用类型在函数里重新赋值,外面看不到(这是和直接传指针的区别)

func reassignSlice(s []int) {
    s = []int{7, 8, 9}  // 只改了本地拷贝的s指向
}

func main() {
    s := []int{1, 2, 3}
    reassignSlice(s)
    fmt.Println(s) // [1 2 3] 没变
}

// 如果真想改外面的s指向,还是要传指针
func reallyReassign(s *[]int) {
    *s = []int{7, 8, 9}
}

3. 关键区别:能否重新指向

  • 指针:你可以让它指向别处,就像门牌号可以贴到另一个房子上。

  • 引用类型:它的指向是“固化”在内部的,你不能让slice变量本身指向另一个底层数组,除非重新赋值。

为什么要有引用类型?

为了方便,避免到处写 *和 &

  • 如果用普通指针操作slice:(*s)[0] = 100 很难看

  • 引用类型直接:s[0] = 100 清爽

面试/学习易错点

  1. new 和 make 的区别

    • new(T) 返回 *T,一个指针,值为零值

    • make(T) 只用于 slice/map/chan,返回 T 本身(但内部已初始化好指针)

  2. nil 指针不能用

    var p *int
    *p = 10 // panic! 空指针解引用
  3. nil slice 可以直接用 append

    var s []int   // nil slice
    s = append(s, 1) // ✅ 可以,Go做了处理

记忆口诀

  • 指针:要 取地址,要 * 取值,可以改指向

  • 引用:用起来像值,传参像指针,不能改本体指向

更多推荐