Go教程:16-什么时候使用指针Pointer

Go教程:16-什么时候使用指针Pointer

1. Pointer指针

指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址.

在计算机科学中,指针(Pointer)是编程语言中的一个对象, 利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值. 由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元.因此,将地址形象化的称为“指针”.意思是通过它能找到以它为地址的内存单元.

1.1 C/C++中复杂的指针

int (*func)(int *p, int (*f)(int*)) 因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的. 如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法. 不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法.C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的.

1.2 Go语言指针

Go语言保留着C中值和指针的区别,但是对于指针繁琐用法进行了大量的简化,引入引用的概念. 所以在Go语言中,您几乎不用担心会因为直接操作内寸而引起各式各样的错误.

3. Go语言指针

每一个变量都会分配一块内存,数据保存在内存中,内存有一个地址,就像门牌号,通过这个地址就可以找到里面存储的数据. 指针就是保存这个内存地址的变量.

3.1 &取得变量的地址

//为了说明类型,我采用了显性的变量定义方法,实际开发中更多的是用“:=”自动获取类型变量类型
var mystr string = "Hello!"
var mystrP *string = &mystr

fmt.Println(mystrP)

3.2 *取得指针变量指向的内存地址的值

在之前的代码的后面增加一句代码:fmt.Println(*mystrPointer)

3.3 nil代表空指针

指针表示指向内存的地址,如果对为nil的指针进行解引用的话就会导致panic.

var p *int
p == nil    // true
*p          // panic: invalid memory address or nil pointer dereference

4. 什么时候使用指针

在Go语言中,默认是按值传递.当一个变量当作参数传递的时候,会创建一个变量的副本, 然后传递给函数或者方法,您可以看到这个副本的地址和变量的地址是不一样的. 当变量当做指针被传递的时候,一个新的指针被创建,它指向变量同样的内存地址, 所以您可以将这个指针看成原始变量指针的副本.

4.1 func Func(t *Type) {} VS func Func(t Type) {}

入参是指针,参数值可以在函数内部被修改.

4.2 func Func()(t *Type) {} VS func Func()(t Type) {}

返回值类型不同之处在于取值的方式,指针类型需要使用 * 号读取数据. 其次返回值指针判断空值更加容易简洁,t != nil.

4.3 func (t *Type) Method() {} VS func (t Type) Method() {}

如果要在方法中更改receiver的状态,操纵receiver的值,请使用指针receiver. 使用值receiver是不可能的, 它按值复制.对值receiver的任何修改都是该值receiver副本的本地修改.

值receiver在原始类型值的副本上运行. 这意味着涉及成本,特别是如果结构非常大,并且接收的指针更有效. 如果您不需要编辑receiver值,请使用值receiver.

值receiver是并发安全的,而指针receiver不是并发安全的.

有一种情况,您可能希望将指针receiver用于通常使用值receiver的方法, 并且当您在该类型上定义了其他指针receiver时,为了保持一致性, 您应该在所有方法中使用指针receiver.

目录