后端青训营day2 | 青训营笔记

51 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第2天

大佬的课讲得很好, 但是好多细节还得自己花时间看, 争取后天读完Go语言圣经.

记录一下一些今天所学.

1. defer语句

为了在函数执行完毕后释放资源, 要使用defer, 延时机制. 比如释放数据库连接, 文件句柄, 锁,等等.

一个小细节: defer语句按定义的逆序进行执行, 先被defer的语句最后被执行,最后被defer的语句,最先被执行.

举个例子:

func main() {
    fmt.Println("start")
    defer fmt.Println(1)
    defer fmt.Println(2)
    defer fmt.Println(3)
    fmt.Println("end")
}

输出结果:

start
end
3
2
1

再来一个小细节: defer 的执行时机, 在Go语言的函数中return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。而defer语句执行的时机就在返回值赋值操作后,RET指令执行前。具体如下图所示: image.png

2. Go语言并发编程

Go语言中的并发程序主要是通过基于CSP(communicating sequential processes)的goroutine和channel来实现,当然也支持使用传统的多线程共享内存的并发方式。设计上我们要遵循:不要通过共享来通信,而要通过通信来共享。

关于channel:

  • 通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。
  • 默认情况下,channel 接收和发送数据都是阻塞的,除非另一端已经准备好
  • 在消费方可以通过语法 v, ok := <-ch 测试 channel 是否被关闭。如果 ok 返回 false,那么说明 channel 已经没有任何数据并且已经被关闭。
  • channel 不像文件之类的,不需要经常去关闭,只有当你确实没有任何发送数据了,或者你想显式的结束 range 循环之类的.
  • 未初始化的通道类型变量其默认零值是nil

关于关闭的通道:

  • 对一个关闭的通道再发送值就会导致 panic。
  • 对一个关闭的通道进行接收会一直获取值直到通道为空。
  • 对一个关闭的并且没有值的通道执行接收操作会得到对应类型的零值。
  • 关闭一个已经关闭的通道会导致 panic。