Go语言的批量相对来说比较简单一些,接下来我们学习一下吧

简介

Go语言的指针有三个概念需要明确一下:指针地址、指针类型及指针取值。任何的程序在载入到内存时,都会给它分配一下地址,而这个地址就是指针,保存这个地址的变量就称为指针变量。

Go语言中的指针是不能进行偏移和运算的,所以操作起来也比较简单,我们只需要记住两个符号就可以了:取地址(&)、地址取值(*)。

指针地址与类型

每个变量在运行的时候都会拥有一个地址,这个地址标识着变量所在的内存位置。Go语言使用&符号对变量进行“取地址”的操作。Go语言中的值类型(如:int、float、bool、string、array、struct)都有对应的指针类型,比如int的指针类型为*int.

取一个变量的指针,语法如下:

ptr := &v

说明:

  • prt - 接收变量指针地址的变量
  • v - 被取地址的变量

来个示例:

func main() {
    a := 20
    b := &a

    fmt.Printf("a: %d, type: %T, ptr: %p\n", a, a, &a)
    fmt.Printf("b: %d, type: %T, ptr: %p\n", *b, b, b)
    fmt.Println(&b) // b同样也有自己的指针地址
}

输出:

a: 20, type: int, ptr: 0x14000016098
b: 20, type: *int, ptr: 0x14000016098
0x1400000e028

指针取值

对获取到的指针进行*号操作,就是指针取值了,如下:

func main() {
    a := 20
    b := &a                           // 将变量a的地址保存在b变量中
    fmt.Printf("type of b : %T\n", b) // 指针类型:*int

    c := *b                            // 对指针进行取指操作
    fmt.Printf("type of c : %T\n", c)  // 值类型:int
    fmt.Printf("value of c : %v\n", c) // 值为:20
}

new和make

上面我们学习了指针相关的知识,我们来看一下小例子:

func main() {
    var a *int
    *a = 200
    fmt.Println(*a)
}

上面的小例子,会报panic异常,原因是Go语言中引用类型的变量不仅要声明它,而且还有对它进行初始化(即分配内存空间,比如map的使用),否则我们的值就没办法存储。而对值类型的声明不需要初始化,是因为它在声明的时候已经默认分配为内存空间了,比如基础数据类型。要分配空间就引出了今天要说的两个主角:new和make,它们两个都是内建函数,而且都是用来分配空间的,那么有什么区别呢?让我们来看一下吧~

new

new是一个内建的函数,格式如下:

func new(Type) *Type

说明:

  • Type - 表示要分配内存的类型
  • *Type - 表示类型的指针,返回的是一个指向该类型内存地址的指针

new其实在实际开发中并不常用,来个小例子看一下吧:

func main() {
    var a *int   // 声明一个int类型的指针变量
    a = new(int) // 对变量进行内存分配
    *a = 20      // 对变量进行赋值,如果不赋值的话,它的值为该类型的默认值
    fmt.Println(*a)
}

输出:

20

make

make也是用来分配内存的,不过它只用于slicemapchan这些类型,而它返回的是这些类型的本身,而不是指针类型的,因为这几个类型都是引用类型的,格式如下:

func make(t Type, size ...IntegerType) Type

make在实际开发中还是比较常用的,比较之前讲的map的初始化,来个小示例吧:

func main() {
    var b map[string]int
    b = make(map[string]int, 2)
    b["score"] = 20
    fmt.Println(b)
}

输入:

map[score:20]

总结一下两者的区别

  • 两都是用来分配内存的。
  • new是对基础类型进行内存分配的,内存对应的值为该类型的默认值,返回的是该类型的指针。
  • make只用于slicemapchan这些类型,返回的是它们本身。