go语言指针常见操作方法

 更新时间:2026年05月09日 10:37:10   作者:讲不出  再见  
指针是存储变量内存地址的变量,声明格式为`*T`,指针用于函数间共享数据、传递结构体等,本文给大家介绍go语言指针常见操作方法,感兴趣的朋友一起看看吧

什么是指针?

指针是存储一个变量的内存地址的,声明一个指针变量的格式如下:

// ptr是指针变量名,*表示是指针类型,*int表示存储的是一个int类型变量的内存地址
var ptr *int

1、关键操作符

符号名称作用示例
&取址符获取变量在内存中的地址,返回指针类型ptr := &num (获取 num 的地址)
*解引用符

1. ‌声明时‌:表示指针类型(如 *int)

2. ‌使用时‌:获取或修改指针指向的具体值

val := *ptr (读取ptr指向的int变量值)

*ptr = 100 (修改ptr指向的int变量值为100)

2、常见操作

package main
import "fmt"
func main() {
    // 1.定义普通变量
    num := 100
    fmt.Printf("普通变量值: %d, 地址: %p\n", num, &num)
    // 2. 声明并初始化指针
    var ptr *int = &num // ptr 存储的是 num 的内存地址
    // 3. 解引用:读取和修改
    fmt.Printf("指针指向的值: %d\n", *ptr) // 输出 100
    *ptr = 200 // 通过指针修改原始变量的值
    fmt.Printf("修改后原始变量值: %d\n", num) // 输出 200,证明原值被改变
}

3、空指针

当指针变量未初始化时,默认为空指针,nil。

go语言底层将nil视为地址为0的特殊变量。

所以,空指针 ptr == nil 为true,但是在打印ptr指向的内存地址时,打印出的是 0x0【就是0】

危险操作:对 nil 指针进行解引用(如 *ptr)会导致程序运行时崩溃(panic: invalid memory address or nil pointer dereference)。

package main
import "fmt"
func main() {
	var ptr *int
	if ptr == nil {
		fmt.Printf("%p", ptr)
	} 
}

4、指针的使用场景

4.1、在函数间共享数据并修改原值

Go 语言默认参数传递是‌值传递‌(拷贝副本)。如果希望在函数内部修改外部变量的值,必须传递指针。

func increment(ptr *int) {
    *ptr++ // 修改指针指向的原始值
}
func main() {
    count := 10
    increment(&count) // 传入地址
    fmt.Println(count) // 输出 11
}

4.2、避免大型数据结构的拷贝开销

对于大型结构体(Struct)或数组,值传递会复制整个数据结构,消耗内存和 CPU。传递指针仅复制一个地址(64位系统占8字节),效率极高。

type BigData struct {
    Items int
}
// 使用指针接收,避免拷贝 10000 个 int
func process(data *BigData) {
    // 处理逻辑
}

5、注意事项

1. 不可取地址的情况

你不能对以下对象使用 & 取地址,否则编译报错 cannot take the address of ...

  • 字面量/常量‌:&42&"hello" 是错误的。
  • Map 的值‌:&m["key"] 是错误的。因为 Map 的值可能随时移动或不存在,Go 禁止直接取 Map 值的地址。如果需要,先将值赋给临时变量再取址。
  • 函数返回值‌:通常情况下,不能直接对函数返回值取地址(除非返回的是指针或可寻址变量)。

2. 切片、Map 和 Channel 的特殊性

  • 切片(Slice)、Map 和 Channel 在 Go 中本身就是‌引用类型‌(底层实现包含指针)。
  • 无需传指针‌:在函数间传递切片或 Map 时,通常直接传递值即可。函数内部对元素内容的修改会反映到原变量上。
  • 例外‌:如果你需要在函数内改变切片的‌长度‌或‌容量‌(例如 append 导致底层数组重新分配),或者替换整个 Map 对象,则需要传递指向切片或 Map 的指针(如 *[]int),但这在日常开发中较少见。

3. 内存逃逸与性能

  • 栈与堆‌:Go 编译器会自动进行“逃逸分析”。如果局部变量的地址被返回或传递给其他 goroutine,该变量会分配到堆上,增加垃圾回收(GC)压力。
  • 适度使用‌:不要滥用指针。对于小的基本类型(int, bool, small struct),值传递往往比指针传递更快,因为指针涉及间接寻址和可能的堆分配。

4. 原子指针与 unsafe

  • sync/atomic.Pointer 提供了无锁的原子指针操作,适用于高并发场景下的状态切换。
  • unsafe.Pointer 允许绕过类型系统进行指针转换,极其危险,不参与 GC 生命周期检查,容易导致悬垂指针或内存破坏。除非编写底层库或驱动,否则严禁在业务代码中使用。

到此这篇关于go语言指针常见操作方法的文章就介绍到这了,更多相关go语言指针内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang中HttpRouter路由的使用详解

    Golang中HttpRouter路由的使用详解

    httprouter 是一个高性能、可扩展的HTTP路由,本文将通过一些简单的示例为大家讲讲httprouter 这个强大的 HTTP 路由是如何使用的,感兴趣的小伙伴可以了解一下
    2023-05-05
  • go语言字符串的拼接和切片方法总结

    go语言字符串的拼接和切片方法总结

    在go语言中,因为字符串只能被访问,不能被修改,所以进行字符串拼接的时候,golang都需要进行内存拷贝,造成一定的性能消耗,这篇文章主要给大家介绍了关于go语言字符串的拼接和切片的相关资料,需要的朋友可以参考下
    2022-11-11
  • Go语言题解LeetCode463岛屿的周长示例详解

    Go语言题解LeetCode463岛屿的周长示例详解

    这篇文章主要为大家介绍了Go语言题解LeetCode463岛屿的周长示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • Go 语言进阶单元测试示例详解

    Go 语言进阶单元测试示例详解

    这篇文章主要为大家介绍了Go 语言进阶单元测试示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Go语言sync.Cond使用方法详解

    Go语言sync.Cond使用方法详解

    Go语言标准库中还包含条件变量 sync.Cond,它可以让一组 Goroutine 都在满足特定条件时被唤醒,每一个sync.Cond结构体在初始化时都需要传入一个互斥锁,接下来我们将通过文中例子了解它的使用方法,感兴趣的同学跟着小编一起来看看吧
    2023-07-07
  • Golang 之协程的用法讲解

    Golang 之协程的用法讲解

    这篇文章主要介绍了Golang 之协程的用法讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • go语言实现全排列的示例代码

    go语言实现全排列的示例代码

    本文主要介绍了go语言实现全排列的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • golang中range在slice和map遍历中的注意事项

    golang中range在slice和map遍历中的注意事项

    今天小编就为大家分享一篇关于golang中range在slice和map遍历中的注意事项,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • Golang创建构造函数的方法超详细讲解

    Golang创建构造函数的方法超详细讲解

    构造器一般面向对象语言的典型特性,用于初始化变量。Go语言没有任何具体构造器,但我们能使用该特性去初始化变量。本文介绍不同类型构造器的差异及其应用场景
    2023-01-01
  • 一文了解Go语言中的函数与方法的用法

    一文了解Go语言中的函数与方法的用法

    与大部分语言一致,Go语言中的函数与方法定义与其他语言基本一致,但也有一定的差别。本文将通过示例详细讲讲Go语言中函数与方法的用法,感兴趣的可以学习一下
    2022-07-07

最新评论