golang学习备忘总结——指针

273 阅读3分钟

定义

指针是golang中的一种数据类型,用于表示数据的内存地址。Go 提供了指针操作,但是没有指针运算。任何程序数据载入内存后,在内存都有他们的地址,可以把这个地址当做指针。而为了保存一个数据在内存中的地址,我们就需要指针变量。

指针的意义

声明一个指针,相当于是创建了一个地址的引用,后续可以根据这个引用获取这个地址里的值。如果这个值发生变化,那么通过指针获取这个值也发生变化。

运算符

  • & 取这个值所在的地址(对值取地址)
  • * 取这个地址里存储的值(对地址取值)

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

假设有个变量i&i表示变量i所在的内存地址,*&i表示i变量所在的内存地址里存储的值,即i变量本身。先有变量,才能取到变量所在的内存地址,所以*& 可以抵消掉,但&*是不可以抵消的,因为顺序不对。

常用操作

指针地址、指针类型、指针取值

指针地址(&i)

代码在运行时,每个变量都需要存储在内存中,这个变量在内存中的位置就是指针地址。Go语言中使用&字符放在变量前面对变量进行“取地址”操作。 取变量指针的语法:ptr := &i,其中:ptr是声明的指针变量,i是被取地址的变量。这个语句的含义是声明一个指针变量ptr,并把变量i的内存地址复制给指针变量ptr。 用一段示例代码加深理解:

func main() {
    var i int = 100
    ptr := &i
    fmt.Printf("变量i的值是:%d,内存地址是:%p\n", i, &i) 
    fmt.Printf("变量ptr的值是:%p,内存地址是:%p\n", ptr, &ptr) 
}

输出:

变量i的值是:100,内存地址是:0xc0000ae018
变量ptr的值是:0xc0000ae018,内存地址是:0xc0000b4018

指针类型(&i)

指针是一种数据类型,但根据值类型的不同(int、float、bool、string、array、struct),对应的指针类型分别是*int*float*bool……

上面代码中ptr := &i的逻辑示意图 指针示意图.drawio.png

  • 变量i的类型int,值100,内存地址0xc0000ae018
  • 因为变量ptr是用i的指针赋值,ptr的类型就为*int,值是i的内存地址0xc0000ae018,同理,作为一个变量(值),ptr也有自己的内存地址0xc0000b4018*代表指针。

指针取值(*&i

在对一个值使用&操作符,可以获得这个值的地址(这个变量的指针),同样的,在对一个指针使用*操作符,可以获得这个内存地址里的值,这个操作就是指针取值。 示例代码

func main() {
	i := 100
	j := &i // 取变量i的地址,并将指针保存到j中
	fmt.Printf("j的类型是:%T\n", j)
	k := *j // 指针取值
	fmt.Printf("k的类型是:%T\n", k)
	fmt.Printf("c的值是:%v\n", k)
}

输出

j的类型是:*int
k的类型是:int
c的值是:100

值传递和指针传递

严格地说,Golang中方法或函数只有一种传递方式,那就是值传递。每次将一个变量作为参数传递时,都会创建一个新的变量副本并将其传递给所调用的函数或方法。副本分配在不同的内存地址。 (待补充)