基本语法

声明

全局变量 局部变量
声明语法 <font style="color:rgb(0, 0, 136);">var</font><font style="color:rgb(0, 0, 0);"> var_name </font><font style="color:rgb(102, 102, 0);">*</font><font style="color:rgb(0, 0, 136);">var</font><font style="color:rgb(102, 102, 0);">-</font><font style="color:rgb(0, 0, 0);">type</font> 比如:
<font style="color:rgb(0, 0, 0);">var ip *int</font>
1. 声明和右边相同
2. 短运算符 b := &a

:::info 指针类型有哪些?

:::

Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型,如:int、int64、*string等。

初始化

Go语言中的指针操作非常简单,只需要记住两个互补操作符&(取地址)和*(根据地址取值)。
  1. 取地址:
    1. ptr := &v // v的类型为T
    2. v和T都是代号
      v:代表被取地址的变量,类型为T
      ptr:用于接收地址的变量,ptr的类型就为T,称做T的指针类型。代表指针。
  2. 取值:prt = &a; b := *prt
  3. 初始化要求
    初始化必须给地址/指针而不能是值——指针不能声明 **<font style="color:rgb(51, 51, 51);">var</font>** a ***<font style="color:rgb(51, 51, 51);">int</font>**之后就 *a = 100(所以我们有了new和make两个内置函数,请见后文)
  4. 空指针——默认初始化为nil
    与c语言不同的是,无须专门赋值指针为空指针,golang中只要没别分配到任何变量时候,默认为nil

与c语言的不同

  1. 语法上
    1. c语言:int* prt;类型是int*
    2. go语言:var prt *int类型是*int——看*的位置,非常不同
  2. 默认值为nil,没有NULL常量,c语言赋予NULL之后可
  3. 不支持指针与整数的算术运算,不支持 ->运算符,直接用.访问目标成员地址

调用

向函数传递指针

和c相同,略

!new和make

看个例子:

  1. func main() {
  2. var a *int
  3. *a = 100//错在这
  4. fmt.Println(*a)
  5. var b map[string]int
  6. b["测试"] = 100//这也错了
  7. fmt.Println(b)
  8. }
执行上面的代码会引发panic,为什么呢?——值类型和引用类型的声明作用不同 1. 对于引用类型的变量,我们在使用的时候不仅要声明它,还要为它分配内存空间,否则我们的值就没办法存储。
只有初始化和new/make内建函数才能为其分配内存 2. 而对于值类型的声明不需要分配内存空间,是因为它们在声明的时候已经默认分配好了内存空间。
可以什么? 不可以什么?
var a *int a = b(b是另一个已经初始化的变量)
=让遥控器指向新电视
a = 100
why? 给我小米遥控器,但还没给我电视,所以无法往里导入节目
+ 小米 =
int
+ 遥控器 = 指针
+ 电视 = 分配内存
+ 导入节目 = 赋值
a = new(int) + a = b
+ *a = 100
给了未激活的电视,只有默认栏目,可以导入节目,也可以让遥控器指向另一个电视

new

函数签名:func **<font style="color:rgb(51, 51, 51);">new</font>**(Type) *Type

其中:

  1. 接受:一个类型Type
  2. 返回:这个类型的指针 *Type

作用:

new函数不太常用,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。(特别注意:这里和默认初始化的nil,也就是空指针,还是有区别我们使用new函数,无需担心其内存的生命周期或者怎样将其删除,因为GO语言的内存管理系统会帮我们打理一切 实例: go func main() { a := new(int) b := new(bool) fmt.Printf("%T\n", a) // *int fmt.Printf("%T\n", b) // *bool fmt.Println(*a) // 0 fmt.Println(*b) // false } 我们要是用new函数来改造上上的例子 go func main() { var a *int a = new(int) *a = 10//这就行了 fmt.Println(*a) } #### make :::info 作用 ::: make也是用于内存分配的,区别于new,它只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

:::info

make函数的函数签名如下:

:::

**<font style="color:rgb(51, 51, 51);">func</font>** **<font style="color:rgb(51, 51, 51);">make</font>**(**<font style="color:rgb(51, 51, 51);">t</font>** **<font style="color:rgb(51, 51, 51);">Type</font>**, **<font style="color:rgb(51, 51, 51);">size</font>** ...IntegerType) **<font style="color:rgb(51, 51, 51);">Type</font>**

切片的创建我们已经了解,后两者后面说

区别

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