Go第十二课-指针

107 阅读4分钟
  1. 取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。

    1. 对变量进行取地址(&)操作,可以获得这个变量的指针变量。
    2. 指针变量的值是指针地址。
    3. 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。
  2. 定义:指针类型是依托某一个类型而存在的,如果我们拥有一个类型 T,那么以 T 作为基类型的指针类型为 *T。

    var p *T
    
  3. 指针地址和指针类型

    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
    }
    
  4. Go 中有一种指针类型是例外,它不需要基类型,它就是 unsafe.Pointer。任何指针类型都可以显式转换为一个 unsafe.Pointer,而 unsafe.Pointer 也可以显式转换为任意指针类型。

    var p *T
    var p1 = unsafe.Pointer(p) // 任意指针类型显式转换为unsafe.Pointer
    p = (*T)(p1)               // unsafe.Pointer也可以显式转换为任意指针类型
    
  5. 如果指针类型变量没有被显式赋予初值,那么它的值为 nil。

    var p *int
    println(p == nil) //true
    
  6. 赋值,变量 a 的地址赋值给指针变量 p,Go 为指针变量 p 分配的内存单元中存储的是整型变量 a 对应的内存单元的地址

    var a int = 13
    var p *int = &a  // 给整型指针变量p赋初值
    
  7. Go语言中new和make是内建的两个函数,主要用来分配内存。

  8. 使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值

    func new(Type) *Type
    // Type表示类型,new函数只接受一个参数,这个参数是一个类型
    // *Type表示类型指针,new函数返回一个指向该类型内存地址的指针。
    
  9. make也是用于内存分配的,区别于new,它只用于slice、map以及channel的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型。

  10. new与make的区别

    1. 二者都是用来做内存分配的。
    2. make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
    3. 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。
  11. unsafe.Sizeof() 返回值的类型 uintptr 是一个整数类型,它的大小足以容纳任何指针的比特模式(bit pattern)。在 Go 语言中 uintptr 类型的大小就代表了指针类型的大小。指针的好处,还包括它传递的开销是常数级的。

  12. 指针变量读取或修改其指向的内存地址上的变量值,这个操作被称为指针的解引用。

    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的解引用反映出来
    
  13. **int 被称为二级指针,也就是指向指针的指针。二级指针就可以用来改变指针变量的值,也就是指针变量的指向。对二级指针 pp 解引用一次,我们得到将是 pp 指向的指针变量。pp 解引用二次,得到的是 pp 指向的指针变量所指向的整型变量。

  14. GO的内存管理与垃圾回收这两个地方,这两个运行时机制只关心指针。

  15. 指针可以改变其指向的内存单元的值:

    1. 使用 *T 类型的变量调用方法、
    2. 以 *T 类型作为函数或方法的形式参数、
    3. 返回 *T 类型的返回值
  16. 对指针的限制,使用unsafe可以绕过。

    1. 限制了显式指针类型转换
    2. 不支持指针运算