-
取地址操作符
&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。- 对变量进行取地址(&)操作,可以获得这个变量的指针变量。
- 指针变量的值是指针地址。
- 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。
-
定义:指针类型是依托某一个类型而存在的,如果我们拥有一个类型 T,那么以 T 作为基类型的指针类型为 *T。
var p *T -
指针地址和指针类型
func mainPointer() { a := 10 b := &a fmt.Printf("a: %d,ptr:%p\n", a, &a) // a: 10,ptr:0xc0000ac008 fmt.Printf("b:%p,type of b:%T\n", b, b) // b:0xc0000ac008,type:*int fmt.Printf("%p\n", &b) // 0xc0000a6018 c := *b fmt.Printf("type of c:%T\n", c) // type of c:int fmt.Printf("value of c:%v \n", c) // value of c:10 } -
Go 中有一种指针类型是例外,它不需要基类型,它就是 unsafe.Pointer。任何指针类型都可以显式转换为一个 unsafe.Pointer,而 unsafe.Pointer 也可以显式转换为任意指针类型。
var p *T var p1 = unsafe.Pointer(p) // 任意指针类型显式转换为unsafe.Pointer p = (*T)(p1) // unsafe.Pointer也可以显式转换为任意指针类型 -
如果指针类型变量没有被显式赋予初值,那么它的值为 nil。
var p *int println(p == nil) //true -
赋值,变量 a 的地址赋值给指针变量 p,Go 为指针变量 p 分配的内存单元中存储的是整型变量 a 对应的内存单元的地址
var a int = 13 var p *int = &a // 给整型指针变量p赋初值 -
Go语言中new和make是内建的两个函数,主要用来分配内存。
-
使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值
func new(Type) *Type // Type表示类型,new函数只接受一个参数,这个参数是一个类型 // *Type表示类型指针,new函数返回一个指向该类型内存地址的指针。 -
make也是用于内存分配的,区别于new,它只用于slice、map以及channel的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型。
-
new与make的区别
- 二者都是用来做内存分配的。
- make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
- 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。
-
unsafe.Sizeof()返回值的类型 uintptr 是一个整数类型,它的大小足以容纳任何指针的比特模式(bit pattern)。在 Go 语言中 uintptr 类型的大小就代表了指针类型的大小。指针的好处,还包括它传递的开销是常数级的。 -
指针变量读取或修改其指向的内存地址上的变量值,这个操作被称为指针的解引用。
var a int = 5 var p1 *int = &a // p1指向变量a所在内存单元 var p2 *int = &a // p2指向变量b所在内存单元 (*p1) += 5 // 通过p1修改变量a的值 println(*p2) // 10 对变量a的修改可以通过另外一个指针变量p2的解引用反映出来 -
**int 被称为二级指针,也就是指向指针的指针。二级指针就可以用来改变指针变量的值,也就是指针变量的指向。对二级指针 pp 解引用一次,我们得到将是 pp 指向的指针变量。pp 解引用二次,得到的是 pp 指向的指针变量所指向的整型变量。
-
GO的内存管理与垃圾回收这两个地方,这两个运行时机制只关心指针。
-
指针可以改变其指向的内存单元的值:
- 使用 *T 类型的变量调用方法、
- 以 *T 类型作为函数或方法的形式参数、
- 返回 *T 类型的返回值
-
对指针的限制,使用unsafe可以绕过。
- 限制了显式指针类型转换
- 不支持指针运算