golang 学习笔记
语法部分
数组 [n]T
语法: 变量名 := [数组长度]数据类型{数组内数据}
例如: country := [3]string{‘中国’,’日本’,’韩国’}
也可以只生命,不赋值,或者不填满数组
var country [5]string
需要注意的是这个时候不能使用 :=
语法允许 var country [5]string
或者 country := [5]string{}
golang 的数组是固定长度的,如果想使用不固定长度的,可以使用切片(slice)
切片 []T
相比数组,切片不需要声明长度,语法是通过两个下标来界定,即一个上界和一个下界,二者以冒号分隔:
slice[low : high] // 默认 low 是 0,high是数组上界
声明切片的方式有 3 种:
从数组上进行切片
1
2array := [5]int{1,2,3,4,5}
slice := array[1:4] // 从数组 array 上切下角标为 1 到 4(不包括)的元素从切片上进行切片
1
2
3array := [5]int{1,2,3,4,5}
slice1 := array[1:4] // [2,3,4]
slice2 := slice[1:2] // [3]单独声明一个切片
1
slice := []int{1,2,3} // [1,2,3] 可以理解为不设置长度的数组就是切片
要注意的是它是一个半开区间,包括第一个元素,但排除最后一个元素
比如: a := [5]int{1,2,3,4,5}
b := a[1:4] // 2,3,4 从 1 下标(包含)开始到 4 下标(不包含)
c := b[0:2] // 2,3
切片并不存储任何数据,它只是引用了底层数组中的一段
切片的长度与容量
切片的长度就是它所包含的元素个数
切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数
切片 s 的长度和容量可通过表达式 len(s) 和 cap(s) 来获取
1 | // 这里的 len 和 js 中的 array.length 一样 |
make 函数
make函数有三个参数,最后一个是可选参数make([]type, len, cap)
1 | package main |
append 函数
append 函数是用户在切片尾部追加元素,功能上类似 push
语法是 append(s []T, …T)
append 的第一个参数 s 是一个元素类型为 T 的切片,其余类型为 T 的值将会追加到该切片的末尾
需要注意的是 append 函数不会改变 s,只会返回追加之后的值,所以需要赋值给 ss = append(s[]T, ...T)
1 | a := [3]int{1,2,3} // 123 |
如果切片是从数组引用来的,那么 append 方法会另外分配一个数组来存储新追加到切片尾部的数据,并不会改变原底层数组
range 语法
for 循环的range 是用来遍历数组、切片(slice)或者映射(map)的
for (let item in array){} 等同于
for _,item := range array {}
例如:
1 | package main |
但是我们在遍历切片时,经常是不需要用到 index 的,比如JS 中的 for in 遍历
这个时候我们可以用_来表示忽略该参数
1 | package main |
结构体 struct
结构体有点类似 js 中的 class,里面放的都是 class 的成员,并不是 map 那样的键值对.
使用 type 和 struct 声明
1 | type Rectangle struct { |
上面这段代码是方法的一种使用场景,奇怪的是把Rectangle作为函数接受对象时,加了个*,也就是使用结构体的指针,为什么不使用指针的时候 rec 的成员没有被改变呢?
不带指针的情况下,方法会拷贝一份新的结构体,这个时候操作的是新结构体的数据,对原结构体没有影响
官方文档也提到:
1.如果你需要在方法/函数内改变Rectangle的值,则必须声明一个指针方法。
2.如果你的Rectangle结构体数据较大,比如有100个字段,如果使用不带指针的方法,则每一次都需要对其进行拷贝,内存消耗较大,此时建议使用带指针的方法。
3.如果有部分方法是带指针的,则为了代码统一,建议其他方法也写成带指针的。