Go 背景
- 高并发、分布式、微服务的爬虫项目
- Go 已成为云原生领域的流行语言 Docker Kubernetes
- Go 是为了应对谷歌在软件工程和基础架构上遇到的困难设计出来的。这些困难包括,软件开发开始变得缓慢和笨拙、软件设计的复杂度越来越高、编译速度越来越慢等等。
- 语言设计者使用第一性原理思维,思考复杂挑战背后的本质问题,并尝试用简单的设计来解决它们。
- Go 和 C 都致力于更接近机器,编译出高效的机器识别的二进制代码。这和 Python 这样的脚步语音以及需要把代码转换为字节码的 Java 有本质的不同。
- Go 借鉴了 CSP(并发系统中通过通道传递消息),并引入了 channel 用于协程间的通信。
Go 特性
良好的编译器和依赖设计
- 无序列表为了加快编译
- package 为使用报错
- 不用编多余的代码
- 编译器优化
- 执行 import 导入包时,它只需要打开一个与导入包相关的 obj 文件,而不是导入依赖的源文件
- 不能有循环依赖
- Go 标准库
面向组合而不是继承
- Java C++ 它们通过将事物抽象为对象和对象的行为,并通过继承等方式实现了对象之间的关联。继承带来了类型的层次结构,使代码变得难以改动,前期过度设计
- 面向组合不仅更容易构建起复杂的程序,而且在后期功能变动时也有很强的扩展性
- 接口,类型实现了接口中的方式,就隐式地实现了该接口。Duck Typing
并发原语
- 多核 CPU ,Go 语言原生支持并发,Go 在线程之上抽象出了更加轻量级的协程,
- 实现了 CSP 并发编程模式,通道成为了 Go 语言中的一等公民。通过通道来共享内存的方式屏蔽了很多底层实现细节
简单与健壮性
- 易上手,语法简单,1.18 加入泛型
- 没有隐式的数值转换、没有指针运算、没有类型别名、运行时会检查数组的边界
- 没有手动的内存管理,垃圾回收
- 内存逃逸功能,这意味着我们可以传递栈上的变量的地址
强大丰富的标准库与工具集
- 软件工程需要包含一整套工具,这样才能更好地完成代码编写、代码编译、代码调试、代码分析、代码测试、代码部署等工作
- go fmt 格式化
- go vet 报告代码中可能的错误
- go doc 生成代码注释
Go 基础知识体系
基础语法
- 变量与类型
- 表达式与运算符
- 基本控制结构
- 函数(对功能的抽象)
- 多返回值
- 可变参数函数
- 递归
- 函数作为参数时,可以提升程序的扩展性
- 函数作为返回值,一般在闭包和构建功能中间件时使用多
- 函数作为值时,可以用来提升服务的扩展性
- 复合类型(数据的抽象)
- 数组、切片、哈希表,以及用户自定义的结构体
- 结构体
- 结构体声明与赋值
- 匿名结构体,经常在测试或者在 JSON 序列化反序列化等场景使用
语法特性
-
defer
- 在资源释放、panic 捕获等场景中应用广泛
- 特性:延迟执行、参数预计算、LIFO 执行顺序
-
接口:模块解耦、代码复用还有控制系统复杂度
- 隐式实现接口
- 接口的动态调用方式
- 接口的嵌套
- 接口类型的断言
- 根据空接口中动态类型的差异选择不同的处理方式(这在参数为空接口函数的内部处理中使用广泛,例如 fmt 库、JSON 库)
-
除此之外,Go 语言的特性包括:处理元数据的反射、处理指针的 unsafe 包,以及调用 c 函数的 cgo 等。
并发编程
-
概念:
- 进程、线程与协程。进程是操作系统资源分配的基本单位,线程是操作系统资源调度的基本单位。而协程位于用户态,是在线程基础上构建的轻量级调度单位。并
- 发与并行。并行指的是同时做很多事情,并发是指同时管理很多事情。
- 主协程与子协程。 main 函数是特殊的主协程,它退出之后整个程序都会退出。而其他的协程都是子协程,子协程退出之后,程序正常运行。
-
如何优雅安全地关闭协程,以及如何进行协程间的通信
- select 监听多个通道实现多路复用。当 case 中多个通道状态准备就绪时,select 随机选择一个分支进行执行
- 用 context 来处理协程的优雅退出和级联退出
-
传统的同步原语:原子锁。Go 提供了 atomic 包用于处理原子操作。
-
传统的同步原语:互斥锁。
-
传统的同步原语:读写锁。适合多读少写场景。
-
除此之外,Go 语言在传统的同步原语基础上还提供了许多有用的同步工具,包括 sync.Once、sync.Cond、sync.WaitGroup。
项目组织 -
依赖管理
-
面向组合:代码与功能的扩展