14-指针

100 阅读2分钟

指针

  • 区别于c/c++中的指针,Go语言中的指针不能进行偏移运算,是安全指针
  • 要搞明白Go语言中的指针需要先知道3个概念: 指针地址指针类型指针取值
  • Go语言中的函数传参都是值拷贝,当我们要修改某个变量的时候,我们可以创建一个指向变量地址的指针变量,传递数据使用指针,而无需拷贝,类型指针不能进行偏移和运算
    • 只需要记住2个符号
      • & 取地址
      • * 根据地址取值

指针地址和指针类型

  • 取指针的语法如下

ptr := &v // v的类型为T

  • v: 代表取地址的变量,类型为T
  • ptr: 用于接收地址的变量,ptr的类型为*T,称之为T的指针类型, *代表指针
package main
import (
    "fmt"
)

func main() {
    a := 10 // int
    b := &a// 获取a的内存地址 *int类型
    fmt.Printf("%v--%p\n", a, &a)// 10--0xc00000e098
    fmt.Printf("%v--%p\n", b, &b)// 0xc00000e098--0xc00000a028

    // 指针取值 b是一个 *int 类型的指针,它存储的是变量a的内存地址
    c := *b
    fmt.Println(c)// 10
}

image.png

总结: 取地址操作符&和取值操作符*是一对互补的操作符, &获取地址,*根据地址取值

指针传值

package main
import (
    "fmt"
)

func main() {
    a := 10
    modify1(a)
    fmt.Println(a)// 10
    modify2(&a)
    fmt.Println(a)// 20
}

func modify1(x int) {
    x = 100
}
func modify2(y *int) {
    *y = 20
}

image.png

new 和 make的初始化

  • var a *int只是声明了一个指针变量a但是没有初始化,指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值
  • make也是用于内存分配的,区别于new,它只用于slice、map以及channel的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了
package main
import (
    "fmt"
)

func main() {
    var a *int
    a = new(int)
    fmt.Println(*a)// 0
    *a = 100
    fmt.Println(*a)// 100

    var b map[string]int
    b = make(map[string]int, 10)
    fmt.Println(b)// map[]
    b["沫沫"] = 100
    fmt.Println(b)// map[沫沫: 100]
}

image.png

new与make的区别

  • 二者都是用来做内存分配的。
  • make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
  • 而new用于基础类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。