网站首页 > 技术文章 正文
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 |
猜你喜欢
- 2025-05-27 Python进阶 - day1:深入理解数据结构
- 2025-05-27 Java中transient字段的作用
- 2025-05-27 深度学习数据集处理常用函数示例(Python)
- 2025-05-27 什么是 happens-before 规则?
- 2025-05-27 「Java」一张图教会你关于null的几种处理方式(内附代码)
- 2025-05-27 Python 中常用的数据结构,帮助你从基础到精通
- 2025-05-27 1、数值类型
- 2025-05-27 基础函数20例,案例解读,再不掌握就真的Out了
- 2025-05-27 12 个 C# 提效实用干货
- 2025-05-27 Java中数组的声明和初始化方法
- 05-27Python进阶 - day1:深入理解数据结构
- 05-27Java中transient字段的作用
- 05-27深度学习数据集处理常用函数示例(Python)
- 05-27Go语言-指针
- 05-27什么是 happens-before 规则?
- 05-27「Java」一张图教会你关于null的几种处理方式(内附代码)
- 05-27Python 中常用的数据结构,帮助你从基础到精通
- 05-271、数值类型
- 最近发表
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- sqlset (64)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)