这是我参与「第五届青训营 」伴学笔记创作活动的第 2天
今天继续记录关于GO语言基础的语法和注意细节
还是继续在掘金课程上学习,因为课程比较短,所以补充了一些别的网站的教学内容
字符串
字符串是用一对双引号("")或反引号(``)括起来定义,它的类型是string。
var s string // 一般方法
var emptyString string = "" // 声明了一个空字符串
GO中的字符串是不可变的,但是可以通过转换为切片的形式修改
s := "hello"
c := []byte(s) // 将字符串转换为 切片
c[0] = 'c'
s2 := string(c) // 再转换回 string 类型
结构体
在结构体中就可以定义多个不同的数据类型。在声明结构体之前我们首先需要定义一个结构体类型,这需要使用type和struct,type用于设定结构体的名称,struct用于定义一个新的数据类型。具体结构如下
type struct_variable_type struct {
member definition
member definition
...
member definition
}
定义好了结构体类型,我们就可以使用该结构体声明这样一个结构体变量
variable_name := structure_variable_type {value1, value2...valuen}
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
如果要访问结构体成员,需要使用点号 . 操作符,格式为:结构体变量名.成员名
array数组
定义
var arr [n]type
n表示数组的长度,type表示存储元素的类型。对数组的操作和其它语言类似,都是通过[]来进行读取或赋值
var arr [10]int // 声明了一个int类型的数组
arr[0] = 42 // 数组下标是从0开始的
arr[1] = 13 // 赋值操作
slice切片
简单地说,切片就是一种简化版的动态数组。因为动态数组的长度不固定,切片的长度自然也就不能是类型的组成部分了。数组虽然有适用它们的地方,但是数组的类型和操作都不够灵活,而切片则使用得相当广泛。
切片高效操作的要点是要降低内存分配的次数,尽量保证append操作(在后续的插入和删除操作中都涉及到这个函数)不会超出cap的容量,降低触发内存分配的次数和每次分配内存大小。
slice的底层结构
type SliceHeader struct {
Data uintptr // 指向底层的的数组指针
Len int // 切片长度
Cap int // 切片最大长度
}
所以slice并不是真正意义上的动态数组,而是一个引用类型。slice总是指向一个底层array,slice的声明也可以像array一样,只是不需要长度。
// 和声明array一样,只是少了长度
var fslice []int
// 接下来可以声明一个slice,并初始化数据
slice := []byte {'a', 'b', 'c', 'd'}
slice可以从一个数组或一个已经存在的slice中再次声明。slice通过array[i:j]来获取,其中i是数组的开始位置,j是结束位置,但不包含array[j],它的长度是j-i。
添加元素: append() :内置的泛型函数,可以向切片中增加元素。
a = append(a, 1) // 追加1个元素
a = append(a, 1, 2, 3) // 追加多个元素, 手写解包方式
删除元素 :
- 从开头位置删除;直接移动数据指针,代码如下:
a = []int{1, 2, 3, ...}
a = a[1:] // 删除开头1个元素
a = a[N:] // 删除开头N个元素
map
map表的底层原理是哈希表,其结构体定义如下:
type Map struct {
Key *Type // Key type
Elem *Type // Val (elem) type
Bucket *Type // 哈希桶
Hmap *Type // 底层使用的哈希表元信息
Hiter *Type // 用于遍历哈希表的迭代器
}
特点如下:
-
map是无序的(原因为无序写入以及扩容导致的元素顺序发生变化),每次打印出来的map都会不一样,它不能通过index获取,而必须通过key获取
-
map的长度是不固定的,也就是和slice一样,也是一种引用类型 内置的len函数同样适用于map,返回map拥有的key的数量
-
map的key可以是所有可比较的类型,如布尔型、整数型、浮点型、复杂型、字符串型……也可以键。
如下方式即可进行初始化:
var a map[keytype]valuetype
除此以外还可以使用make进行初始化
map_variable = make(map[key_data_type]value_data_type)
使用初始值初始
var m map[string]int = map[string]int{"hunter":12,"tony":10}
插入数据
map_variable["mars"] = 27
插入过程如下:
- 根据key值计算出哈希值
- 取哈希值低位和hmap.B取模确定bucket位置
- 查找该key是否已经存在,如果存在则直接更新值
- 如果没有找到key,则将这一对key-value插入
delete(map, key) 函数用于删除集合的元素, 参数为 map 和其对应的 key。删除函数不返回任何值。
countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi"}
// 删除元素
delete(countryCapitalMap,"France");
error
Go内置有一个error类型,专门用来处理错误信息,Go的package里面还专门有一个包errors来处理错误
err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
fmt.Print(err)
}
总结
以上没有对go语法的全部内容进行记录,还包括函数,一些关键字,接口,channel。go还有很多东西需要我去学习总结,整体来说go有着c语言的很多特征,语法结构又与python类似。