【入门】Go语言指针详解
目录
一、指针介绍
1.1 什么是指针?
- 指针是一种存储变量内存地址的变量。
- Go 语言中的指针与 C/C++ 中的指针类似,但是 Go 语言中的指针不能进行指针运算,也不能进行指针类型转换。
1.2 指针有什么用?
在Go语言中,指针是一种特殊的变量,它存储了一个变量的内存地址。通过指针,我们可以直接访问和修改变量的值,而不需要拷贝变量本身,这样可以提高程序的效率。指针在Go语言中有以下几个作用:
-
传递变量的地址:指针可以作为函数参数,将变量的地址传递给函数,这样函数就可以直接修改变量的值。
-
动态分配内存:通过指针可以在运行时动态分配内存,这样程序就可以根据需要动态地创建和销毁变量。
-
访问复杂数据结构:指针可以用于访问复杂的数据结构,如链表、树等,通过指针可以方便地遍历和修改这些数据结构。
-
函数返回值:指针可以作为函数的返回值,这样函数就可以返回一个指向变量的指针,而不是变量本身,这样可以避免变量拷贝和内存分配的开销。
二、指针的定义
语法:
var 指针变量名称 *指针类型
如下案例:通过指针修改变量的值
package main
import "fmt"
func main() {
var a int = 100
var p *int = &a
// 通过指针修改变量的值
*p = 666
fmt.Printf("a变量的值:%v\ta变量的内存地址:%v", a, p)
}
代码输出内容:
a变量的值:666 a变量的内存地址:0xc000018098
三、指针操作注意事项
3.1 空指针
定义完成指针变量后,没有声明任何内存地址,那么就是空指针。
var p *int
fmt.Println(p)
3.2 操作没有合法指向的内存
没有指向内存地址,直接操作
var p *int
*p = 666 // 没有指向内存地址,直接操作
fmt.Println(p)
3.3 new()函数使用
开辟数据类型对应的内存空间,返回值为数据类型指针
var p *int
p = new(int) //int占用4字节,也就是开辟4字节的内存空间,给p指针变量
*p = 666
fmt.Println(p)
四、拓展
4.1 指针变量作为函数参数
在函数内,修改变量的值
package main
import "fmt"
func main() {
var num int = 100
EditVariable(&num)
fmt.Println(num)
}
func EditVariable(p *int) {
*p = 666
}
代码输出内容:
666
4.2 切片数组(将数组指针作为函数参数)
首先先看下基本操作案例:
package main
import "fmt"
func main() {
var nums = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
var p *[10]int = &nums // 指针指向nums数组
fmt.Println(*p)
fmt.Println((*p)[0]) // []优先级小于* 所以在前面要加()来先计算()内容
fmt.Println(p[0]) // 等价于上面写法
// 遍历数组
fmt.Println("==============================")
for i := 0; i < len(p); i++ {
fmt.Println(p[i])
}
}
代码输出内容:
[1 2 3 4 5 6 7 8 9 0]
1
1
==============================
1
2
3
4
5
6
7
8
9
0
再来看下 数组指针作为函数参数。
package main
import "fmt"
func main() {
var nums = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
var p *[10]int = &nums // 指针变量指向nums数组
UpdateArr(p)
fmt.Println(nums)
}
func UpdateArr(p *[10]int) {
p[5] += 10
}
代码输出内容:
[1 2 3 4 5 16 7 8 9 0]
4.3 指针数组(数组元素是指针类型)
指针数组指的是一个数组中存储的都是指针(就是内存地址),也就是一个存储了地址的数组。
定义语法:
var 数组名 [下标]*类型
package main
import "fmt"
func main() {
var nums [2]*int
a, b := 100, 200
nums[0] = &a
nums[1] = &b
// 输出指针数组内容
fmt.Println(nums)
// 输出指针数据内存地址对应的值
fmt.Println(*nums[0])
// 循环变量指针数组
for i := 0; i < len(nums); i++ {
fmt.Println(*nums[i])
}
}
代码输出内容:
[0xc000018098 0xc0000180b0]
100
100
200
4.4 切片与指针
定义指针,指向切片,也就是这个指针保存了切片的地址,可以通过地址修改切片中的值。
package main
import "fmt"
func main() {
s := []int{100, 200, 300, 400}
var p *[]int = &s
// 输出下标为0的值,需要优先计算*p,所以这里添加了小括号
fmt.Println((*p)[0])
// 修改值
(*p)[2] = 3666666
fmt.Println((*p)[2])
// 变量循环
fmt.Println("====================")
for i := 0; i < len(*p); i++ {
fmt.Println((*p)[i])
}
}
代码输出内容:
100
3666666
====================
100
200
3666666
400
4.5 结构体与指针
定义指针,指向结构体
package main
import "fmt"
type Class struct {
id int
name string
age int
}
func main() {
var zhangsan Class = Class{100, "zhangsan", 10}
var p *Class = &zhangsan
fmt.Println((*p).age)
fmt.Println(p.age) // 等价于上面写法
// 通过指针修改结构体成员内容
p.age = 100
fmt.Println(p.age)
}
代码输出内容:
10
10
100
结构体指针作为函数参数,在函数中修改结构体内容,会影响到原来的值。
package main
import "fmt"
type Class struct {
id int
name string
age int
}
func main() {
var zhangsan Class = Class{100, "zhangsan", 10}
var p *Class = &zhangsan
UpdateStr(p)
fmt.Println(zhangsan)
}
func UpdateStr(str *Class) {
str.name = "lisi"
str.age = 666
}
代码输出内容:
{100 lisi 666}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南