Go语言指针详解:地址、取值与new/make区别

桃夭
桃夭
发布时间:2026-10-15 | 4人浏览过
原创

Go语言的指针操作简单但强大,掌握取地址符(&)和解引用符(*)是核心。本文从基础概念出发,通过完整代码演示指针变量的创建与使用,解析函数传参时的值传递问题,并深入剖析内存分配机制中make与new的本质区别及常见错误排查。

1. 什么是Go语言的指针

在Go语言中,指针变量存储的是另一个变量的内存地址。与普通C或C++不同,Go的指针不支持算术运算(如加减偏移),其核心优势在于能够直接访问和修改变量的值,从而避免在大对象传递时产生昂贵的数据拷贝开销。

掌握指针需要明确三个关键概念:

  • 指针地址:变量在内存中的实际位置。
  • 指针类型:指针本身的数据类型,如*int指向整型。
  • 指针取值:根据地址获取变量存储的值。

操作中只需记住两个符号:&用于获取变量地址,*用于根据地址取值。

2. 指针地址与指针类型

Go语言中的一切变量在运行时均拥有唯一的内存地址。对于基本数据类型(如int, string, float, bool)以及数组和结构体,都有对应的指针类型。

以下代码展示了如何定义一个整型变量并获取其指针:

package main

import "fmt"

func main() {
    a := 10 /* 声明实际变量 */
    ip := &a /* 指针变量ip存储a的地址 */
    
    // 输出a的直接地址
    fmt.Printf("a 变量的地址是: %x\n", &a)
    
    // 输出指针ip中储存的地址值
    fmt.Printf("ip 变量储存的指针地址: %x\n", ip)
    
    // *ip 代表对ip进行解引用,即取出该地址里的值
    fmt.Printf("*ip 变量的值: %d\n", *ip)
}

运行结果如下:

a 变量的地址是: 0xc000010200
ip 变量储存的指针地址: 0xc000010200
*ip 变量的值: 10

在该示例中,a是类型为int的变量,而ip被赋值为&a,因此ip的类型自动推断为*int。

这种内存关系的可视化表现如下:

3. 指针取值与函数传参

获取指针后,可以通过*操作符来读取或修改内存中的数据。这一特性在函数传参时尤为关键。默认情况下,Go语言采用“值传递”(即值拷贝),这意味着在函数内部修改参数不会影响原始变量。

若要修改外部变量,必须传递变量的指针:

package main

import "fmt"

func main() {
    x := 2
    
    mod1(x) // 传入值,x 保持为 2
    fmt.Println(x) 
    
    mod2(&x) // 传入指针,x 变为 1024
    fmt.Println(x) 
}

// 仅接收副本,无法改变主调函数的变量
func mod1(x int) {
    x = 1024
}

// 接收指针,通过解引用修改原始内存
func mod2(x *int) {
    *x = 1024
}

4. Go中的内存分配:new与make

在处理指针时,常会涉及内存初始化关键字new和make,二者虽然都涉及内存分配,但用途有严格区分。

第1步:使用 new 分配内存

new(Type)函数会为Type类型的零值分配一块内存空间,并返回指向该内存的*Type指针。

package main

import "fmt"

func main() {
    a := new(int) // 返回 *int 类型
    b := new(bool)
    
    fmt.Printf("%T\n", a) // 输出: *int
    fmt.Printf("%T\n", b) // 输出: *bool
    
    // 指针指向的初始值是类型零值
    fmt.Println(*a) // 0
    fmt.Println(*b) // false
}

第2步:使用 make 初始化引用类型

make仅适用于内置引用类型:slice(切片)、map(映射)和chan(通道)。它的返回值就是这三个类型本身,而非它们的指针。

package main

import "fmt"

func main() {
    var user map[string]int
    // 必须使用 make 分配内存,否则 user 仍为 nil
    user = make(map[string]int, 10)
    
    user["age"] = 18
    fmt.Println(user) // map[age:18]
}

核心区别小结

  • 返回值:new返回指针*Type;make返回类型本身。Type。
  • 适用对象:new用于所有类型的内存分配;make专用于 slice, map, channel 的内部数据结构初始化。

5. 常见问题排查:Nil Pointer Dereference

初学者常遇到panic: runtime error: invalid memory address or nil pointer dereference报错。这通常发生在使用未分配内存的指针或未初始化的引用类型时。

package main

import "fmt"

func main() {
    var a *int
    // 错误示范:a是nil指针,不能直接赋值
    *a = 100 
    
    var user map[string]int
    // 错误示范:user未make,是nil map,不能直接赋值
    user["age"] = 18 
}

**原因**:引用类型(如map)和空指针必须先进行内存分配。解决方法是给指针赋予有效地址(使用new或指向已存在变量),并在使用map、slice前调用make。

[] 以上就是Go语言指针及内存分配机制的详细内容,更多关于Go语言基础知识资料请关注本站其它相关文章!
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表