基本语法对比

声明 值长什么样?
整型/浮点型/复数/字符串/字符 var a int 25/26.3/10 + 2*i/"good"/'g'
指针 var prt *int 0**<font style="color:rgb(51, 51, 51);">xc0000a0063</font>** 一般用*prt 或者 prt
/ new(int)
数组 **<font style="color:rgb(51, 51, 51);">var</font>** a [<font style="color:rgb(0, 128, 128);">5</font>]**<font style="color:rgb(51, 51, 51);">int</font>** [5]int{1,2,3,4,5}
切片 var a []string []int{1,2,3,4,5,6}
集合 var a [string] int map[string]int{"Tom":1, "Bob":2} (集合必须写key-value,不能像结构那样省略,因为集合是无序地)
结构体 type person struct{....} + var man_1 person person{"Bob": 24, "Justin":23 }
/ 可以不写key,如person{24, 23},但要求 全部、按序、不能混地初始化

思想

要用模块化的思想,而非分支,因为分支实在太多

  1. 仅声明var x type
  2. 初始化
    1. 左边
      var x =/ x :=
    2. 右边——数据
      1. 数据长什么样必须清楚,尤其是数组、切片、集合、结构体,上图已展示
    3. 特殊情况需要 var a type = ...
      什么特殊情况?——type是自定义的,相对比较复杂的
      1. 结构体不需要,因为值里带了结构体类型别名
      2. 函数类型变量推荐写(好像也没那么需要)
      3. 自定义类型,由于实现方法的类型,必须经过type定义,故在方法里最常用
        <font style="color:#E8323C;">type Myint int</font> <font style="color:#E8323C;">var x Myint = 10</font>
  3. 类型
    1. 仅声明,类型必须有
    2. 若使用var关键字
      1. var x int/float/string/complex64 右边类型必须要
      2. 对于指针、数组、切片、集合、结构体 。。。。,尾巴可省略——var x
    3. 注意,不像python用方括号和花括号区分不同组合类型,而通过开头
      • 数组 [...]int {1,2,3,4,5}
      • 切片 []int{1,2,3,4,5}
      • 集合 map[string]int{...:..., ...:,... }
      • 结构体 person{...:..., ...:...}(person是之前已经定义好的类型)
数组 切片 集合 结构体
范围 全局var a / 局部 a := 范围和左侧相同,这里只提一个结构体指针注意一下
1. 全局变量var man_1 = ...(如果左边写变量类型,一般变量写person,结构体型指针写*person)
2. 局部变量 man_1 := ...
类型处理
1. 结构体类型长这样:struct{...}int/float/...同地位 如struct{Name string; Age int}
2. 直接用——匿名结构体
1. 和声明变量一起 var user struct{Name string; Age int}
2. 和初始化一起 声明器 - 图1
3. 先定义结构类型,之后再用 声明器 - 图2
声明 1. 由于数组是值类型,声明与初始化为零值作用相同
1. 声明**<font style="color:rgb(51, 51, 51);">var</font>** a [len]**<font style="color:rgb(51, 51, 51);">type</font>**
2. 初始化为零值:**<font style="color:rgb(51, 51, 51);">var a = [5]type{}</font>**/ a := [len]type{}
var s_1 []type 仅声明,之后可以整体赋值,但是不可单独赋值
并不推荐,因为切片是引用类型,仅仅只是声明无初始化为零值,系统并未分配底层数组
var a [string]int仅仅声明,并未初始化,不可调用,不推荐 仅变量声明 var man_1 person/ var man_1 *person

1. 结构就一值类型,和int、float、string….同地位, 仅声明=初始化为零值 (结构体指针不同,必须初始化为零值或者给予地址后才可以用) 声明器 - 图3
2. 初始化成什么变量?
1. 一般变量 右边—— person{}
2. 指针变量 右边——&person{}/右边——new(perosn)
初始化为零值 等式右边
1. 设定len和cap:make ([]type, len, cap)
2. 不设定 :[]type{}
等式右边:
1. **<font style="color:rgb(51, 51, 51);">make</font>**(**<font style="color:rgb(51, 51, 51);">map</font>**[string]int, 5, 7)
2. <font style="color:#c7773e;">map</font>[<font style="color:#c7773e;">string</font>]<font style="color:#c7773e;">int</font>{}
初始化 1. {}怎么塞?
1. 一维数组
1. 不完全赋值[5]int{1, 2, 3} /[5]string{3: "hello world", 4: "tom"}
2. 完全赋值 [5]int{1, 2, 3, 4, 5}/[...]int{1, 2, 3, 4, 5, 6}
2. 多维数组
1. [2][3]int{{1, 2, 3}, {7, 8, 9}}
2. 可省略第一个[...][3]int{{1, 2, 3}, {7, 8, 9}}
2. 用下标,挨个赋值 arr [i] =
3. 组合 **类型——注意一下struct类型 **声明器 - 图4
1. 直接塞[]type {...., ....}
2. 截取别的数组 other_s [a:b:c](a,b,c皆可省略) **重点知道cap怎么计算**

直接赋值
声明器 - 图5
挨个赋值
map_1[key] = value
赋值
1. 塞花括号:用键值对/ 只给value 声明器 - 图6 声明器 - 图7
2. 挨个赋值:<font style="color:rgb(51, 51, 51);">man_1.name = ... </font>
调用 下标 a[3] 下标s_1[3] map_1[key] = value <font style="color:rgb(51, 51, 51);">man_1.name = ... </font>
多维 如果是多维数组,则类型改成 [len_1][len_2]type
如果要赋值: [len_1][len_2]type{{1, 1}, {2, 2}, {3, 3}}
如果是二维度切片,目前不知道make怎么弄,但直接赋值可,且二维切片可不同维度不同维数
声明器 - 图8

组合

???

初始化

值类型声明,即初始化为零值,但引用类型声明后,初始化为nil,必须实例化/初始化为零值后才可调用

关键字

type

类型定义

<font style="color:rgb(18, 18, 18);">type typeName baseType</font>

  • typeName 为定义的类型名称
  • baseType 依赖的类型,Go 语言中所有的数据类型都可以,还有待会要讲的结构体 struct

:::info 应用

:::

给类型定义类型别名,什么情况会需要呢?

  1. 自定义类型(复合)
    1. 结构体
      声明器 - 图9
    2. 函数类型
      type 类型别名 函数类型比如 type Func_type func(a, b int)
  2. 一般变量别名
    type MyInt **<font style="color:rgb(51, 51, 51);">int</font>**_<font style="color:rgb(153, 153, 136);">//将MyInt定义为int类型</font>_

类型别名

  1. 语法结构:<font style="color:rgb(0, 134, 179);">type</font> TypeAlias = Type
    1. 类型别名是Go1.9版本添加的新功能。
    2. 类型别名规定:TypeAlias只是Type的别名,本质上TypeAlias与Type是同一个类型。就像一个孩子小时候有小名、乳名,上学后用学名,英语老师又会给他起英文名,但这些名字都指的是他本人。
  2. 实例:
    我们之前见过的rune和byte就是类型别名,他们的定义如下:
    <font style="color:rgb(0, 134, 179);">type</font> byte = uint8
    <font style="color:rgb(0, 134, 179);">type</font> rune = int32

区别

上面其实已经说明了,主要表现于类型转化上

  1. 类型定义,是创建一个全新类型,即使 type str_type string; var str_1 str_type = "good"
    声明器 - 图10
  2. 类型别名,不创建新的类型,只是多一个指针,仍然指向原类型
    知乎解释:
    声明器 - 图11

创建变量的函数

make

  1. a := make([]string, len, cap)
  2. b := make([string]int, len)//len=cap
  3. c := 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>**

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

new

为创建指针而生

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

其中:

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

作用:

new函数不太常用,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。(特别注意:这里和默认初始化的nil,也就是空指针,还是有区别

实例:

  1. func main() {
  2. a := new(int)
  3. b := new(bool)
  4. fmt.Printf("%T\n", a) // *int
  5. fmt.Printf("%T\n", b) // *bool
  6. fmt.Println(*a) // 0
  7. fmt.Println(*b) // false
  8. }

由于用new函数创建指针,其值为对应其类型的零值,故可直接赋值

  1. func main() {
  2. var a *int
  3. a = new(int)
  4. *a = 10//这就行了
  5. fmt.Println(*a)
  6. }

其他

成员运算符—点号.

  1. 访问结构体成员,结构体.结构体成员=该结构体成员的值
  2. 方法:
    1. 基本运用符合接收者类型的变量.方法(...参数)
    2. 方法值,隐藏方法和接收者,
      pFunc := var_receiver.apFunc(...参数)
    3. 方法表达式,隐藏方法,保留接收者,
      pFunc := (receiver).methodpFunc(...var_receiver, ...参数)
      receiver是接收者类型,var_receiver是符合接收者类型的变量
  3. 接口
    1. 接口变量.方法
  4. 某包的函数/方法调用
    包.函数/方法比如fmt.Printf(...)