1、接⼝
1)概念:
接⼝是⼀个或多个⽅法签名的集合,任何类型的⽅法集中只要拥有与之对应的全部⽅法,就表⽰它 "实现" 了该接⼝,⽆须在该类型上显式添加接⼝声明。
所谓对应⽅法,是指有相同名称、参数列表 (不包括参数名) 以及返回值。当然,该类型还可以有其他⽅法。
• 接⼝命名习惯以 er 结尾,结构体。
• 接⼝只有⽅法签名,没有实现。
• 接⼝没有数据字段。
• 可在接⼝中嵌⼊其他接⼝。
• 类型可实现多个接⼝。
2)空接口
空接⼝ interface{} 没有任何⽅法签名,也就意味着任何类型都实现了空接⼝。其作⽤类似⾯向对象语⾔中的根对象 object。
3)接口执行机制:
接⼝对象由接⼝表 (interface table) 指针和数据指针组成。
只有 tab 和 data 都为 nil 时,接⼝才等于 nil。
接⼝表存储元数据信息,包括接⼝类型、动态类型,以及实现接⼝的⽅法指针。
4)接口调用成员变量
2、并发
Go 在语⾔层⾯对并发编程提供⽀持,⼀种类似协程,称作 goroutine 的机制。只需在函数调⽤语句前添加 go 关键字,就可创建并发执⾏单元。开发⼈员⽆需了解任何执⾏细节,调度器会⾃动将其安排到合适的系统线程上执⾏。 goroutine 是⼀种⾮常轻量
级的实现,可在单个进程⾥执⾏成千上万的并发任务。
事实上,⼊⼝函数 main 就以 goroutine 运⾏。另有与之配套的 channel 类型,⽤以实现 "以通讯来共享内存" 的 CSP 模式。CSP(communicating sequential processes)并发模型。——"不要通过共享内存来通信,而应该通过通信来共享内存"。
调度器不能保证多个 goroutine 执⾏次序,且进程退出时不会等待它们结束。
1)默认情况下,进程启动后仅允许⼀个系统线程服务于 goroutine。可使⽤环境变量或标准库函数 runtime.GOMAXPROCS 修改,让调度器⽤多个线程实现多核并⾏,⽽不仅仅是并发。
2)调⽤ runtime.Goexit 将⽴即终⽌当前 goroutine 执⾏,调度器确保所有已注册 defer延迟调⽤被执⾏。
3)Gosched 让出底层线程,将当前 goroutine 暂停,放回队列等待下次被调度执⾏。
3、Channel
1)基本应用:
引⽤类型 channel 是 CSP 模式的具体实现,⽤于多个 goroutine 通讯。其内部实现了同步,确保并发安全。默认为同步模式,需要发送和接收配对。否则会被阻塞,直到另⼀⽅准备好后被唤醒。
package main
import "fmt"
func main() {
data := make(chan int) // 数据交换队列
exit := make(chan bool) // 退出通知
go func() {
for d := range data { // 从队列迭代接收数据,直到 close 。
fmt.Println(d)
}
fmt.Println("recv over.")
exit <- true // 发出退出通知。
}()
data <- 1 // 发送数据。
data <- 2
data <- 3
close(data) // 关闭队列。
fmt.Println("send over.")
<-exit // 等待退出通知。
}
输出:
1 2 3
send over.
recv over.
异步⽅式通过判断缓冲区来决定是否阻塞。如果缓冲区已满,发送被阻塞;缓冲区为空,接收被阻塞。
除⽤ range 外,还可⽤ ok-idiom 模式判断 channel 是否关闭。
向closed channel 发送数据引发 panic 错误,接收⽴即返回零值。⽽ nil channel,⽆论收发都会被阻塞。
内置函数 len 返回未被读取的缓冲元素数量, cap 返回缓冲区⼤⼩。
2)单向channel:
可以将 channel 隐式转换为单向队列,只收或只发。
3)选择
如果需要同时处理多个 channel,可使⽤ select 语句。它随机选择⼀个可⽤ channel 做收发操作,或执⾏ default case。在循环中使⽤ select default case 需要⼩⼼,避免形成洪⽔。
4)模式
a、⽤简单⼯⼚模式打包并发任务和 channel。
b、⽤ closed channel 发出退出通知。
c、⽤select 实现超时 (timeout)。
4、⼯作空间
编译⼯具对源码⺫录有严格要求,每个⼯作空间 (workspace) 必须由 bin、 pkg、 src 三个录组成。
5、内存布局
了解对象内存布局,有助于理解值传递、引⽤传递等概念。