m := map[string]int {"a":1, "b":2}

其实是make的语法糖,它等价于

var m map[string]int = make(map[string]int, 2)
m = {"a":1, "b":2}

内建函数 make 用来为 slice,map 或 chan 类型分配内存和初始化一个对象(注意:只能用在这三种类型上),跟 new 类似,第一个参数也是一个类型而不是一个值,跟 new 不同的是,make 返回类型的引用而不是指针,而返回值也依赖于具体传入的类型。

  • make 的作用是初始化内置的数据结构,也就是我们在前面提到的切片、哈希表和 Channel
  • new 的作用是根据传入的类型分配一片内存空间并返回指向这片内存空间的指针

Channel

func f1(c chan int, x int) // 无向channel
func f2(c chan<- int, x int)  // 只写channel,函数内只能向channel写数据,不能读,send-only channel
func f3(c <-chan int, x int)  // 只读channel,receive-only channel

Unbuffered channel

一个基于无缓存Channels的发送操作将导致发送者goroutine阻塞,直到另一个goroutine在相同的Channels上执行接收操作,当发送的值通过Channels成功传输之后,两个goroutine可以继续执行后面的语句。反之,如果接收操作先发生,那么接收者goroutine也将阻塞,直到有另一个goroutine在相同的Channels上执行发送操作。

Goroutine

Hint

main函数也是一个goroutine,称之为主goroutine.

不管一个channel是否被关闭,当它没有被引用时将会被Go语言的垃圾自动回收器回收。(不要将关闭一个打开文件的操作和关闭一个channel操作混淆。对于每个打开的文件,都需要在不使用的时候调用对应的Close方法来关闭文件。)

select

C 语言的 select 系统调用可以同时监听多个文件描述符的可读或者可写的状态,Go 语言中的 select 也能够让 Goroutine 同时等待多个 Channel 可读或者可写,在多个文件或者 Channel状态改变之前,select 会一直阻塞当前线程或者 Goroutine。

select 是与 switch 相似的控制结构,与 switch 不同的是,select 中虽然也有多个 case,但是这些 case 中的表达式必须都是 Channel 的收发操作。

在通常情况下,select 语句会阻塞当前 Goroutine 并等待多个 Channel 中的一个达到可以收发的状态。但是如果 select 控制结构中包含 default 语句,那么这个 select 语句在执行时会遇到以下两种情况:

  1. 当存在可以收发的 Channel 时,直接处理该 Channel 对应的 case
  2. 当不存在可以收发的 Channel 时,执行 default 中的语句;