channel管道与goroutine协程
一.goroutine协程
一.概述
- Go协程的特点
- 有独立的栈空间
- 共享程序堆空间
- 调度是由程序员(用户)控制
- 协程是轻量级的线程
- 在go语言中,有一种模式叫做MPG,M表示内核线程,也可以称为一个工作线程,P代表执行一个go代码片段的基础(上下文环境),G表示协程,一个线程可以有多个协程。
- 在go语言中可以轻轻松松的启动上万个协程,换做别的语言就不行,这也是go语言的一个特点
- 多线程程序在单核上运行叫做并发
- 多线程程序在多核上运行叫做并行
- 主函数执行并不会等待协程函数运行,不管是协程有没有运行完毕,只要是主函数运行完毕都会直接退出
二.goroutine的使用
- 可以看到,两个函数都是交替的输出,都是同时在一起运行的,只需要在函数面前加一个go表示启动一个协程运行
- 代码块
package main
import (
"fmt"
"time"
)
func myGoroutine() {
for {
fmt.Println("myGoroutine()一秒输出一次")
time.Sleep(time.Second)
}
}
func main() {
/*
- Go协程的特点
- 有独立的栈空间
- 共享程序堆空间
- 调度是由程序员(用户)控制
- 协程是轻量级的线程
*/
// goroutine是调度执行一个函数,也可以是匿名函数
go myGoroutine()
for {
fmt.Println("main()一秒输出一次")
time.Sleep(time.Second)
}
}
二.channel管道
一.概述
- 如果说goroutine是Go语言程序的并发体的话,那么channels则是它们之间的通信机制。一个channel是一个通信机制,它可以让一个goroutine通过它给另一个goroutine发送值信息。每个channel都有一个特殊的类型,也就是channels可发送数据的类型。一个可以发送int类型数据的channel一般写为chan int。
- 创建一个chan必须要用make进行分配空间,而且长度都是固定的,不能动态增长,用途就是存一个取一个
- chan类型是引用类型
- x:= <-chan 接收值
- <-chan 丢弃值
- chan<- x 写入值
- chan可以用全局Close函数进行关闭,关闭过后只能读不能取,否则会报错
二.channel的使用
- chan声明,写入,读取
- 在关闭了一个管道后不能写入,否则会抛出一个Panic错误,不能写入一个关闭了管道
- 关闭了管道可以读取
- 代码块
package main
import "fmt"
func main() {
// 声明一个chan并且分配空间
chs := make(chan int, 3)
// 写入ch
chs<- 10
// close(chs)
chs<- 20
chs<- 30
// 读取 ch
num1 := <-chs
num2 := <-chs
num3 := <-chs
fmt.Printf("num1=%v,num2=%v,num3=%v", num1, num2, num3)
// fmt.Printf("num1=%v,", num1)
}