Go 语言中的指针(Let‘s Go 九)

本文介绍了Go语言中指针的基本概念及其使用方法,包括指针的声明、获取指针指向的值以及通过指针修改值等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

笔者个人网站:秋码记录

本文已首发于秋码记录:Go 语言中的指针(Let’s Go 九)

说到指针,想必很多人会谈虎色变吧,在c/c++语言中那晦涩难懂的指针,曾几何时,让人望而却步!

虽说,指针操作效率是相当的快,可一旦把握不好,就会造成可怕的错误。

c/c++语言不同的是,在Go中是不允许进行指针运算的。

1、声明指针

类型 *T 是指向 T 类型值的指针。其默认值为 nil

var name *type
var p *int

其实,每个变量在运行时,在内存都有属于自己的内存地址,而这个地址就是代表着变量在内存的位置。

c/c++语言一样,要想获取变量在内存的地址,只需在变量前面加个&即可。

func main() {
    v := "https://qiucode.cn"
    ptr := &v
}

其中,&v表示取变量v的内存地址,而变量 v 的内存地址又赋值给变量ptr,此时变量ptr类型为*string,称作string的指针类型,* 代表指针。

package main

import "fmt"

func main() {

	var age int = 4

	v := "https://qiucode.cn"
	ptr := &v

	fmt.Printf("%p %p", &age, ptr)
}

  • 指针的值是带有0x十六进制前缀的一组数据。

在这里插入图片描述

2、获取指针指向的值

当我们使用&操作符对普通变量取地址,在得到变量的指针后,接着使用*操作符对普通变量进行取值,也就是指针取值

package main

import "fmt"

func main() {
	// 准备一个字符串类型
	var webSite = "https://qiucode.cn"
	// 对字符串取地址, ptr类型为*string
	ptr := &webSite
	// 打印ptr的类型
	fmt.Printf("ptr 的类型: %T\n", ptr)
	// 打印ptr的指针地址
	fmt.Printf("ptr 指针地址: %p\n", ptr)
	// 对指针进行取值操作
	value := *ptr
	// 取值后的类型
	fmt.Printf("value 类型: %T\n", value)
	// 指针取值后就是指向变量的值
	fmt.Printf("value 指向变量的值: %s\n", value)
}

在这里插入图片描述

取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

  • 对变量进行取地址操作使用&操作符,可以获得这个变量的指针变量。
  • 指针变量的值是指针地址。
  • 对指针变量进行取值操作使用*操作符,可以获得指针变量指向的原变量的值。

3、指针修改值

指针不仅可以取值,还可以修改值

package main

import "fmt"

// 交换函数
func swap(a, b *string) {
	// 取a指针的值, 赋给临时变量t
	t := *a
	// 取b指针的值, 赋给a指针指向的变量
	*a = *b
	// 将a指针的值赋给b指针指向的变量
	*b = t
}
func main() {
	// 准备两个变量, 赋值1和2
	siteName, webSite := "秋码记录", "https://qiucode.cn"
	// 交换变量值
	swap(&siteName, &webSite)
	// 输出变量值
	fmt.Println(siteName, webSite)
}

在这里插入图片描述

代码说明如下:

  • 第 6 行,定义一个交换函数,参数为 a、b,类型都为*string 指针类型
  • 第 8 行,取指针 a 的值,并把值赋给变量 t,t 此时是 string类型。
  • 第 10 行,取 b 的指针值,赋给指针 a 指向的变量。注意,此时*a的意思不是取 a 指针的值,而是 a 指向的变量
  • 第 12 行,将t的值赋给指针 b 指向的变量
  • 第 16 行,准备 siteNamewebSite两个变量,分别赋值为 秋码记录https://qiucode.cn,类型为 string
  • 第 18 行,取出 siteNamewebSite地址作为参数传给 swap() 函数进行调用。
  • 第 20 行,交换完毕时,输出 siteNamewebSite的值。

*操作符作为右值时,意义是取指针的值,作为左值时,也就是放在赋值操作符的左边时,表示 a 指针指向的变量。其实归纳起来,*操作符的根本意义就是操作指针指向的变量。当操作在右值时,就是取指向变量的值,当操作在左值时,就是将值设置给指向的变量

如果swap()操作的是指针值,那会发生什么情况呢?

package main

import "fmt"

func swap(a, b *string) {
	b, a = a, b
	fmt.Printf("swap 函数中, a内存地址=%p,b内存地址=%p. a=%s,b=%s \n", a, b, *a, *b)
}
func main() {
	// 准备两个变量
	siteName, webSite := "秋码记录", "https://qiucode.cn"
	// 交换变量值
	swap(&siteName, &webSite)
	fmt.Printf("main 函数中,siteName内存地址=%p,webSite内存地址=%p \n", &siteName, &webSite)
	// 输出变量值
	fmt.Println(siteName, webSite)
}

在这里插入图片描述

从运行结果可以看出,变量siteName与变量webSite并没有交换值。上述的swap()函数交换了两个变量的地址,在swap()函数块里,ab变量值确实被交换了,但和ab关联的siteNamewebSite两个变量并没有实际关联。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甄齐才

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值