社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
Go 主线程(有程序员直接称为线程/也可以理解成进程): 一个 Go 线程上,可以起多个协程,你可以
这样理解,协程是轻量级的线程[编译器做优化]
Go 协程的特点
1、一个简单的案例
func test(){
for i:=0;i<10;i++{
time.Sleep(time.Second)
fmt.Println("hello world")
}
}
func main() {
go test()
for i:=0;i<10;i++{
time.Sleep(time.Second)
fmt.Println("hello golang")
}
}
2、总结:
异步累加案例:
var s =0
func sum(a int){
s+=a
}
func main() {
for i:=0;i<100;i++{
go sum(i)
}
time.Sleep(time.Second*2)
fmt.Println(s)
}
每次执行出现的结果可能会不一样
问题一、什么时候累加结束?
问题二、协程A累加后的s值会覆盖协程B累加后的s值吗?
如何解决?
对s进行加锁,并加入n告诉程序什么时候累加结束。
var (
s = 0
n = 0
lock sync.Mutex
)
func sum(a int){
lock.Lock()
defer lock.Unlock()
s+=a
n++
}
func main() {
for i:=0;i<100;i++{
go sum(i)
}
for{
if n == 100{
break
}
}
fmt.Println(s)
}
似乎这个已经完美解决了所有问题。但是我们使用线程的目的是什么?效率
这里就需要使用channel了
var 变量名 chan 数据类型
举例:
var intChan chan int (intChan 用于存放 int 数据)
var mapChan chan map[int]string (mapChan 用于存放 map[int]string 类型)
var perChan chan Person
var perChan2 chan *Person
channel 是引用类型
channel 必须初始化才能写入数据, 即 make 后才能使用
管道是有类型的,intChan 只能写入 整数 int
func main() {
//演示一下管道的使用
//1. 创建一个可以存放 3 个 int 类型的管道
var intChan chan int
intChan = make(chan int, 3)
//2. 看看 intChan 是什么
fmt.Printf("intChan 的值=%v intChan 本身的地址=%pn", intChan, &intChan)
//3. 向管道写入数据
intChan<- 10
num := 211
intChan<- num
intChan<- 50
// intChan<- 98//注意点, 当我们给管写入数据时,不能超过其容量
//4. 看看管道的长度和 cap(容量)
fmt.Printf("channel len= %v cap=%v n", len(intChan), cap(intChan)) // 3, 3
//5. 从管道中读取数据
var num2 int
num2 = <-intChan
fmt.Println("num2=", num2)
fmt.Printf("channel len= %v cap=%v n", len(intChan), cap(intChan)) // 2, 3
//6. 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告 deadlock
num3 := <-intChan
num4 := <-intChan
num5 := <-intChan
fmt.Println("num3=", num3, "num4=", num4, "num5=", num5)
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!