Go语言-指针(go语言指针和c指针区别)

Go 语言指针(Pointer)

指针是Go语言的重要特性之一,用于存储变量的内存地址,从而实现高效的数据访问和修改。


1. 指针的基本概念

指针是存储变量内存地址的变量,通过指针可以访问或修改变量的值。

(1) 指针的定义

var p *int  // 声明一个指向 int 类型的指针变量
  • *int 表示 p 是一个指向 int 类型变量的指针
  • p 的默认值是 nil(空指针)

2. 获取变量地址(&)

可以使用 & 取地址符 获取变量的内存地址:

a := 42
p := &a  // p 存储变量 a 的地址
fmt.Println(p)  // 输出 a 的内存地址,例如:0xc0000100a0

3. 通过指针访问和修改值(*)

可以使用 * 解引用(Dereference) 指针,访问或修改指针指向的值:

a := 10
p := &a  // 获取 a 的地址
fmt.Println(*p)  // 访问 a 的值,输出 10

*p = 20  // 修改 a 的值
fmt.Println(a)  // 输出 20

4. 指针的零值(nil)

未初始化的指针默认值为 nil,表示它没有指向任何变量:

var p *int
fmt.Println(p)  // 输出 <nil>

使用 nil 指针会导致运行时错误(runtime error)。


5. 指针的应用

(1) 通过指针修改函数外部变量

在 Go 语言中,函数参数是值传递,如果想要修改外部变量的值,需要使用指针:

func updateValue(p *int) {
    *p = 100  // 通过指针修改变量的值
}

func main() {
    x := 10
    updateValue(&x)  // 传递变量的地址
    fmt.Println(x)  // 输出 100
}

(2) 指针与数组

指针可以指向数组的第一个元素:

arr := [3]int{1, 2, 3}
p := &arr[0]  // 指向数组第一个元素
fmt.Println(*p)  // 输出 1

p++  // 指针偏移,指向下一个元素(不推荐使用,Go 不支持指针运算)

推荐使用切片(slice)代替指针操作数组

func modifySlice(s []int) {
    s[0] = 100  // 直接修改原数组
}

func main() {
    arr := []int{1, 2, 3}
    modifySlice(arr)
    fmt.Println(arr)  // 输出 [100 2 3]
}

(3) 指针与new

new 用于分配内存,返回指针

p := new(int)  // 分配一个 int 类型的内存
*p = 42
fmt.Println(*p)  // 输出 42
  • new(int) 创建一个 int 类型变量,默认值为 0
  • p 是指向该变量的指针

(4) 指针与struct

type Person struct {
    Name string
    Age  int
}

func main() {
    p := &Person{"Alice", 25}
    fmt.Println(p.Name)  // 直接访问字段,不需要 (*p).Name
}

Go 自动解引用 结构体指针,p.Name 等价于 (*p).Name。


6. 指针与unsafe包(高级用法)

Go 语言不支持指针运算,但 unsafe 包提供了低级指针操作:

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    x := [3]int{1, 2, 3}
    p := unsafe.Pointer(&x[0]) // 获取数组首元素的指针
    fmt.Println(p)
}

注意:unsafe 包涉及底层操作,慎用!


7. 指针 VS 值类型

方式

值传递

指针传递

传递方式

传递变量的副本

传递变量的地址

内存占用

复制整个值,占用更多内存

只复制地址,节省内存

修改变量

不影响原变量

可以修改原变量

适用场景

简单数据类型(int、float、string)

需要修改原数据(结构体、大数据对象)

示例:

func modifyValue(x int) {
    x = 100
}

func modifyPointer(p *int) {
    *p = 100
}

func main() {
    a := 10
    modifyValue(a)
    fmt.Println(a)  // 输出 10(未修改)

    modifyPointer(&a)
    fmt.Println(a)  // 输出 100(已修改)
}

总结

操作

语法

作用

取变量地址

p := &a

获取变量 a 的地址

访问指针值

*p

访问 p 指向的值

修改指针值

*p = 100

修改 p 指向的变量值

空指针

var p *int = nil

p 为空指针

new 分配内存

p := new(int)

创建 int 变量并返回指针

结构体指针

p := &Person{"Alice", 25}

指向 struct

原文链接:,转发请注明来源!