课程笔记:Go 语言基础语法|青训营

107 阅读4分钟

XiaYi-7.25.

后端 7.25 第一门课程的课堂笔记,记不熟悉的。

函数使用之类的就先不记录了,比如处理字符串的方法。

变量声明

使用 var 来初始化变量,如果不加上类型那编译器会自动推断,如果不显式赋值则变量为零值:

var a, b int = 1, 2
var (
    name string = "xiayi"
    age  int    = 22
)
var c

constvar 用法类似,区别是 const 声明的变量值在编译期就必须确定。

使用短变量声明操作符,也就是简短声明 :=,可以同时声明和初始化变量。它的规则是至少有一个变量被声明,但不要求全部变量都是声明。也就是说,这样的代码是合法的:

a := 1
a, b := 3, 2 // 最终 a = 3, b = 2

注意 := 只能在函数体内部使用。

控制流

条件控制 if: 不需要条件小括号,但是必须有大括号;条件判断的类型必须是布尔类型;可以在条件判断前添加一个简短声明,它的作用域是 if 块内部,包括可能的 else 等。

循环 for:不加条件判断就是死循环;基本 for 三段式中的任意一段都可以省略,第一段可以是赋值也可以是简短声明;第一段搭配 range 使用就是对集合的遍历。

分支控制 switchswitch 后的表达式不需要加括号;不需要显式加 break,但可以显式加 fallthrough 来继续执行;如果 switch 后没有表达式,那么 case 后可以是一系列条件表达式,相当于 if 语句的集合。

数组和切片

数组是一个值类型,赋值通过拷贝实现。

数组的长度在定义时就固定,长度放在类型前:

arr := [3][2]int{
    {1, 2},
    {3, 4},
    {5, 6}, // 这里的逗号不能省略
}

如果不指定长度,就获得了一个切片,切片是对数组的引用:

s0 := []int{1, 2, 3}
s1 := []int{} // 空切片
var s2 []int // nil 切片, 没有初始化, 没有底层数组, s2 == nil

这是字面量创建切片的方式。不能只填一部分长度,那不合法。

可以通过 make 函数创建有初始长度和容量的切片,容量可以省略长度必须指定:

s0 := make([]int, 5, 10)
s1 := make([]int, 5) // 容量为 5

切片提供了许多操作:查询长度(len(s));查询容量(cap(s));追加元素(s = append(s, element));截取(s[i:j])等等。

几乎所有的操作都可以在 nil 切片上运行。比如 copy,如果将 nil 切片作为 dst,那么不会有任何元素得到复制,因为 copy 只会复制 dst 长度的元素。

Go 中的 map 是一种无序键值对,引用类型,它在存储前一定要初始化:

var m map[string]int // nil map, string -> int, m == nil
m["xiayi"] = 1 // panic
m = make(map[string]int, 10) // 10 可有可无
m["xiayi"] = 1 // safe

其余操作都是安全的,包括读取和删除。读取会返回两个值,第二个表示是否存在;删除不存在的 key 也不会引发错误。

除了使用 make 初始化,还可以用字面量初始化:

m := map[string]struct{
    x, y int
}{
    "a": {1, 2},
    "b": {3, 4},
}

遍历

可以通过 for + range 来遍历数据类型,range 只和 for 一起用。

数组和切片会得到下标值和当前位置的内容;map 会得到 key-value 键值对。

如果不需要某个值可以用 _ 作为站位符。

指针

可以通过 . 来通过指针访问变量的字段,不可以用 ->

结构体

结构体是值类型,可以通过指针避免拷贝。

初始化结构体可以通过字面量和 new 的方式:

type user struct {
    name string
    pswd string
}

a := user{name: "hwd", pswd: "1024"}
b := user{pswd: "1024"}
c := user{"hwd", "1024"} // 按顺序
var d, e *user = new(user), &user{}

可以通过在函数的 func 关键字后边加上 this 的声明来表示这是结构体方法:

type user struct {
    name string
    pswd string
}

func (u *user) resetPswd(pswd string) {
    u.pswd = pswd
}

带指针和不带指针的区别是能否修改变量值。

结构体还可以带标签,可以运行时通过 reflect 包获取,实际应用于序列化和反序列化、数据库操作等:

type user struct {
    name string `json: "Name" db: "user_name"`
    pswd string
}

这种标签用反引号包围,内容遵循 key:"value" 格式,多个这样的内容对可以通过空格分隔。