侧边栏壁纸
  • 累计撰写 47 篇文章
  • 累计收到 0 条评论

玩转 GoLang 指针

2023-1-11 / 0 评论 / 164 阅读
温馨提示:
本文最后更新于 2023-1-11,已超过半年没有更新,若内容或图片失效,请留言反馈。

什么是指针?

指针其实就是一个变量, 用于存储另一个变量的内存地址。

那么什么是变量呢?在现代计算机体系结构中所有的需要执行的信息代码都需要存储在内存中,为了管理存储在内存的数据,内存是划分为不同的区域的,不同区域都用内存地址来标识。一个典型的内存地址是个16进制的8位数(一个字节)比如0xAFFFF(这是一个内存地址的十六进制表示)。

要访问数据,我们需要知道它的存储地址。我们可以跟踪存储与我们的程序相关的数据的所有内存地址。但是要记住这些内存地址,非常费劲,怎么办呢?

于是我们引入了变量的概念。变量只是给存储数据的内存地址的好记的别名。指针也是一个变量。但它是一种特殊的变量,因为它存储的数据不仅仅是一个普通的值(如整数或字符串),而是另一个变量的内存地址。

在上面的图中,指针p 指向 变量a 的地址值0x0001, 那么 指针p 的值是跟随 变量a 的地址值变化而变化的。

指针声明

T类型的指针使用以下语法声明:

var p *int // 表示 p指针 只能保存int变量的内存地址。

指针的零值,不是0,而是nil。任何未初始化的指针值都为nil

初始化指针、指针解引用及指针值修改

初始化一个指针,只需给他赋予其他变量的内存地址。变量的地址可以使用使用&运算符获得:

var x int = 199

var p *int = &x  // 也可以简写为: var p = &x   -> 编译器会自动推断指针变量的数据类型

fmt.Println(p)   // 输出指针p的值, 即变量x的内存地址: 0xc0000b2008

// 获得指针指向地址的值, 也叫做解引用
fmt.Println(*p)  // 输出指针p对应变量x 内存地址的值: 199 (也可以说是指针p的内存地址对应的值). 

fmt.Println(&p)  // 输出指针p的内存地址: 0xc00001a0b8

fmt.Println(*&p) // 输出指针p的内存地址对应的值, 即变量x的内存地址: 0xc0000b2008 , 同 fmt.Println(&*p) 的结果是一样的

// 修改指针变量的值
*p += 100
fmt.Println(*p) // 输出: 299

通过上面代码的解释, 应该也基本理解了指针。

多重指针

指针可以指向任何类型的变量, 所以也可以指向另一个指针。

var x int = 199
var p *int = &x
var pp **int = &p
fmt.Println(**pp)   // 输出: 199 (原理其实是一样的, 只是一层层取值而已)

Go 中没有指针算术

在 C/C++ 中是可以对指针做计算的,但是 Golang 就不支持那样做了。

var x int = 199
var p *int = &x
var p1 = p + 1   // Compiler Error: invalid operation

但是,Golang 中可以使用 == 运算符来比较两个相同类型的指针是否相等。

var x int = 199
var p *int = &x
var p1 *int = &x
if p == p1 {
  fmt.Println("ok")
} else {
  fmt.Println("no")
}



当然, 对于 Golang 算术, 仅仅依靠 == 运算符来说事, 确实显得很勉强。

评论一下?

OωO
取消