最近面试成功了腾讯教育子公司。以后得从事Go语言开发相关工作啦,特此在这记录下Go基础学习。
参考链接: https://tour.go-zh.org/
Go并发
goroutine
goroutine说到底其实就是协程,但是它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部实现了goroutine间的内存共享。执行goroutine只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩。goroutine比thread更易用、更高效、更轻便。
Go程
Go 程(goroutine)是由 Go 运行时管理的轻量级线程。
// 会启动一个新的 Go 程并执行 f(x, y, z)
go f(x, y, z)
信道 (<-)
信道是带有类型的管道,你可以通过它用信道操作符 <- 来发送或者接收值。
这些值只能是特定的类型:channel类型。定义一个channel时,也需要定义发送到channel的值的类型。注意,必须使用make 创建channel
ci := make(chan int)
cs := make(chan string)
cf := make(chan interface{
})
无缓冲通道
- make(chan int),开辟的通道是一种无缓冲通道,所以当对这个缓冲通道写的时候,会一直阻塞等到某个协程对这个缓冲通道读
无缓存通道要先接受,后发送 (或者是用Go程发送)
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
// 将 sum 发送至信道 c。
// 当对这个缓冲通道写的时候,会一直阻塞等到某个协程对这个缓冲通道读
c <- sum // 将和送入 c
}
func main() {
s := []int{
7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
// 从 c 接收值并赋予 x y。
x, y := <-c, <-c // 从 c 中接收
fmt.Println(x, y, x+y)
}
带缓冲的信道
信道可以是 带缓冲的。将缓冲长度作为第二个参数提供给 make 来初始化一个带缓冲的信道。
仅当信道的缓冲区填满后,向其发送数据时才会阻塞。当缓冲区为空时,接受方会阻塞。
// 前4个元素可以无阻塞的写入。当写入第5个元素时,代码将会阻塞,直到其他goroutine从channel 中读取一些元素,腾出空间。
ch := make(chan bool, 4)
range循环信道需要配合close关闭
发送者可通过 close 关闭一个信道来表示没有需要发送的值了。接收者可以通过为接收表达式分配第二个参数来测试信道是否被关闭:若没有值可以接收且信道已被关闭,那么在执行完
v, ok := <-ch
之后 ok 会被设置为 false。
循环 for i := range c 会不断从信道接收值,直到它被关闭。
应该在生产者的地方关闭channel,而不是消费的地方去关闭它,这样容易引起panic
queue := make(chan string, 2