Go语言快速上手笔记(一) | 青训营笔记

989 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第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) //将产生一个恐慌