这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
Go语言简介
什么是Go语言:
1.性能相比其他编程语言更高,通过协程实现高效的高并发
2.语法简单(如循环只有for循环),学习曲线平缓
3.丰富的标准库,大部分时间不需要使用第三方库,而且标准库的版本迭代更好,没有繁琐的配置和版本问题。
4.完善的工具链,官方库中提供了各式各样的工具
5.静态链接。
6.快速编译。
7.语言本身可在linux,mac,windows系统均兼容
8.拥有良好的垃圾回收机制
go的历史与语言优势
go语言本身非常年轻,发布于2009年,C语言是上世纪70年代诞生的语言,C++是80年代诞生的,python是1991年诞生的,java是1995年诞生的,相比而言,go是目前流行语言中最年轻的,是在这些众多语言肩膀上诞生的语言,是由google支持的开源语言,属于静态的编译型语言,由三位语言专家共同编写。
go语言的优势
- 简单易学:只有25个关键字
- 开发速度快:比java好多了,和python差不多
- 性能好:是编译型语言,编译完是字节码,“一处编译,到处运行”;同时可以很方便地引用C语言
- 支持高并发:使用协程,考虑了很多并发场景和资源消耗的问题。
- 生态环境好:很多优秀开源项目是用go做的,例如docker,K8S,ETCD,console,codis,TaiDB,都是基于golang开发的。
go的容器
数组(Array)
- 数组的类型,取决于数组中的元素类型和数组的长度,其中数组的长度不可变
- [N]T,N表示数组的长度,T表示数组的元素类型,比如[10]int
- 注意数组的长度和类型,只要有一项不一样,就不能算作一样的数组,属于不同的类型。
- 数组类型是值类型,不是引用类型,故函数传递数组参数的时候是值拷贝,函数内部使用的是数组的备份,不会影响初始的数组。
- 数据声明时未显式初始化的元素会隐式初始化为类型对应的0(如数字0、空字符串、false等)。
切片(Slice)
- []T,T表示切片中的元素类型
- 切片的结构
type slice struct{
Data unsafe.Pointer
Len int
Cap int
}
- 切片包含了对一段底层数组的动态引用,以及长度和容量
- 长度表示已经有几个元素,容量表示一共能放多少元素
-
定义的一般方法
- a := make([]int,4,6)
- 第一个是切片类型,第二个数是len,第三个数是capacity,再append 只能在len之后append。
-
定义的其他方法
- var num = [10]int{0,1,2,3,4,5,6,7,8,9}
- b := num[2:5:8]
- 第一个是start,第二个数是end,第三个数是capacity
- 越容量访问会报panic
- 注意slice赋值时底层数组是否相同,若直接将sliceA的一部分赋给sliceB,则修改一方时另一方会跟着改动。
-
为避免这种浅拷贝,可以使用Go的内置函数copy,可以做到深拷贝。
- slice1 := []int{1,2,3,4,5,6}
- slice2 := make([]int,3)
- copy(slice2,slice[1:4])
- 前者是destination,后者是source
-
还有个常用函数是append,用于向切片后面加元素
- slice1 := make([]int,0,10)
- slice1 = append(slice,1,2,3)
- 注意如果加元素后超出容量后就会造成切片的扩容:整个容量在1024以下时,每次扩容*2;超过1024后,每次增加四分之一的容量。还要注意每次扩容go会新开辟一块空间,将原来的内容拷贝过来,所以这个操作还是会占据一定性能的。
- 注意slice[i]是引用改动,但是for-range(for _,n := range slice{用n进行操作})循环是值改动,不会对slice产生实际影响。
映射(Map)
- 映射的定义:map[k]T
- key,value结构:students["Jack"] = 11
- 可用delete删除元素:delete(students,"Jack")
- 也用make生成:students := make(map[string]int)
- 注意遍历顺序不是插入顺序(指for-range方法 for k,v := range students {})
- golang没有内置集合(Set)类型,用Map来实现Set
- 数组、切片、映射这几个容器都不是并发安全的。
结构体与接口
结构体(Struct)
- struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套其他结构体,也可以定义方法。
- 封装性:字段首字母大写包外可访问、小写包外不可访问
- 继承:用聚合实现继承(把父类放到子类里)
- tag:定义特定格式中的形式或约束条件,书写:
- 结构体的方法:收参是A结构体就是A结构体的方法。
-
结构体的初始化:
- 直接初始化:person := Person{}
- 使用new:返回的是指针
- 类似数组,也有值传递和引用传递的区别,不传指针就没法改
- 注意,指针和非指针对字段的访问都是用.:person.Age =
接口(Interface)
- 接口描述了某个类型有哪些方法,或者说一个接口类型,定义了一个方法集。
- 通过接口可以实现多:
type Animal interface {
Shout()
}
type Dog struct{}
type Cat struct{}
func (d Dog) Shout(){
fmt.PrintIn("汪汪")
}
func (c Cat) Shout(){
fmt.PrintIn("喵")
}
- 空接口可以被认为是很多其他语言中的any类型;空接口中没有任何方法,所以任何类型都实现了空接口==》
-
为什么PrintIn什么都能打印?
- func Println(a ... interface{}) (n int,err error)
- 因为里面入参是一堆空接口,而go中万物都是空接口
补充:类型断言
var x interface{} = 123
n,ok := x.(int)
fmt.Println(n,ok) //123 ,true
a = x.(float64) //将产生一个恐慌