news 2026/4/23 15:40:51

Go 语言指针

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Go 语言指针

Go 里的指针不复杂,但非常实用,不像 C/C++ 那么危险,也不像 Java 那样完全看不到。

一、Go 指针是什么

1. 指针的本质

指针 = 变量的内存地址

var a int = 10 var p *int = &a
  • a:值是10

  • &a:a 的地址

  • p:指向a的指针

  • *p:通过指针访问a的值

fmt.Println(a) // 10 fmt.Println(p) // 0xc00001a0a8(地址) fmt.Println(*p) // 10

口诀:
& 取地址,解引用*

2. Go 指针的“安全边界”

和 C/C++ 不同,Go:

  • 不能指针运算(p++不存在)

  • 不能随便转类型

  • 有 GC(不用手动 free)

  • 空指针是nil

var p *int fmt.Println(p == nil) // true

二、Go 指针使用场景

1. 修改函数外的变量(非常核心)

❌ 值传递(改不到外面):

func add(a int) { a++ } func main() { x := 10 add(x) fmt.Println(x) // 10 }

✅ 指针传递:

func add(a *int) { *a++ } func main() { x := 10 add(&x) fmt.Println(x) // 11 }

Go 只有值传递,但“指针的值”可以指向同一块内存

2 结构体 + 指针(Go 的高频用法)

type User struct { Name string Age int } func grow(u *User) { u.Age++ } func main() { u := User{Name: "Tom", Age: 18} grow(&u) fmt.Println(u.Age) // 19 }

注意: Go 一个很贴心的地方:

u.Age++ // 等价于 (*u).Age++

Go 自动帮解引用,不需要满屏*

3. new / & 的区别

p1 := new(int) // *int,值是 0 p2 := &User{} // *User

等价写法:

var a int p := &a

一般习惯:

  • 基本类型:&

  • 结构体:&User{}或构造函数

三、Go 指针的核心使用场景

场景 1:需要修改对象本身(最常见)

func updateName(u *User) { u.Name = "Jack" }

场景 2:避免大对象拷贝(性能 & 内存)

type BigStruct struct { Data [100000]int } func process(b *BigStruct) { // 不拷贝 100000 个 int }

场景 3:区分“没传”和“传了零值”

这个在 API / JSON / DB 特别重要

type Req struct { Age *int `json:"age"` }
  • nil→ 前端没传

  • 0→ 前端明确传了 0

场景 4:方法接收者用指针(Go 面向对象)

func (u *User) Grow() { u.Age++ }

什么时候用指针接收者?

  • 需要修改对象

  • 结构体比较大

  • 保证方法一致性(推荐)

官方建议:一个结构体,要么全指针接收者,要么全值接收者

场景 5:与 interface 配合

type Writer interface { Write() } type File struct{} func (f *File) Write() {} var w Writer w = &File{} // 正确

这样不行,因为方法在*File上:

w = File{} // 没实现接口

场景 6:并发 & 共享状态

需谨慎使用

var count int var mu sync.Mutex func inc() { mu.Lock() count++ mu.Unlock() }

虽然不是“显式指针”,但底层都是共享内存 + 地址

四、Go 指针 vs Java/C++

对比GoJavaC++
手动内存
指针运算
空指针nilnullnullptr
参数传递值传递值传递(引用语义)值/引用

Go 指针 = “受控版 C 指针 + Java 引用的灵活性”

五、新手常见坑

❌ 对 map / slice 再取指针

func f(m *map[string]int) // 一般没必要

因为:

  • map / slice 本身就是“引用类型”

  • 直接传就能改

❌ nil 指针解引用

var u *User u.Age = 10 // panic

一定要先初始化。

六、总结

Go 指针的目标只有三个:

  1. 修改原数据

  2. 减少拷贝

  3. 表达“可选值”

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 12:29:13

PHP 8.6错误码全曝光:你必须知道的15个致命Error及其修复方案

第一章:PHP 8.6 错误码机制概述PHP 8.6 引入了更加精细化的错误码机制,旨在提升开发者在调试和异常处理过程中的效率与准确性。该版本通过标准化错误码命名、增强异常类层次结构以及提供更详细的上下文信息,使运行时问题的定位更为直观。错误…

作者头像 李华
网站建设 2026/4/23 12:29:28

Kafka副本管理核心机制解析

以下内容是 Apache Kafka 中 ReplicaManager 类(或其子类)的一部分,主要负责管理副本(replica)的状态、日志、高水位(High Watermark)、故障处理、选举等核心功能。下面我将逐段解释其作用和逻辑…

作者头像 李华
网站建设 2026/4/23 12:29:17

Kafka高水位与日志末端偏移量解析

在 Apache Kafka 中,HW(High Watermark,高水位) 和 LEO(Log End Offset,日志末端偏移量) 是两个核心概念,它们共同保障了 Kafka 的数据一致性、可靠性与可见性。理解它们的关系对掌握…

作者头像 李华
网站建设 2026/4/23 12:29:13

探索Xilinx FPGA:千兆以太网与DDR内存读写测试之旅

xilinx fpga千兆以太网+ddr内存读写测试代码 基于kcu105/kc705平台的10/100/1000m 以太网lwip通信+ddr4 内存读写测试 工程代码在FPGA开发的世界里,实现千兆以太网通信与DDR内存读写功能是许多项目的关键需求。今天,咱们就来聊聊基…

作者头像 李华
网站建设 2026/4/23 15:30:35

我在小米推了两年的方向,字节用豆包手机助手做出来了

我在小米推了两年的方向,字节用豆包手机助手做出来了 张和 张和专业讲AI 2025年12月14日 13:12 张和|前小米 8 年 AI 产品负责人|现 AI 创业公司创始人 (做过手机 OS 级 AI、也做过自动驾驶数据闭环,更早在小米 AI 实…

作者头像 李华