Go_channel(管道)
Posted yzg-14
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go_channel(管道)相关的知识,希望对你有一定的参考价值。
1. 计算阶乘
package main import ( "fmt" _ "time" "sync" ) //需求:现在要计算 1-200 的各个数的阶乘,并且把各个数的阶乘放入到map中。 //最后显示出来。要求使用goroutine完成 //思路 //1. 编写一个函数,来计算各个数的阶乘,并放入到 map中. //2. 我们启动的协程多个,统计的将结果放入到 map中 //3. map 应该做出一个全局的. var ( myMap = make(map[int]int, 10) //声明一个全局的互斥锁 //lock 是一个全局的互斥锁, //sync 是包: synchornized 同步 //Mutex : 是互斥 lock sync.Mutex ) //test 函数就是计算 n!, 让将这个结果放入到 myMap func test(n int) { res := 1 for i := 1; i <= n; i++ { res *= i } //这里我们将 res 放入到myMap //加锁 lock.Lock() myMap[n] = res //concurrent map writes? //解锁 lock.Unlock() } func main() { //我们这里开启多个协程完成这个任务[20个] for i := 1; i <= 20; i++ { go test(i) } //休眠10秒钟【第二个问题 】 //time.Sleep(time.Second * 5) //这里我们输出结果,变量这个结果 lock.Lock() for i, v := range myMap { fmt.Printf("map[%d]=%d ", i, v) } lock.Unlock() }
为什么输出结果需要加锁
2. 为什么需要channel
2.1 队列
2.2 管道声明
package main import ( "fmt" ) func main() { //演示一下管道的使用 //1. 创建一个可以存放3个int类型的管道 var intChan chan int intChan = make(chan int, 3) //2. 看看intChan是什么 fmt.Printf("intChan 的值=%v intChan本身的地址=%p ", intChan, &intChan) //intChan 的值=0xc000094000 intChan本身的地址=0xc00008e018 //3. 向管道写入数据 intChan <- 10 num := 211 intChan <- num intChan <- 50 //如果从channel取出数据后,可以继续放入 <-intChan //取出来扔了,不要 intChan <- 98 //注意点, 当我们给管写入数据时,不能超过其容量 //4. 看看管道的长度和cap(容量) fmt.Printf("channel len= %v cap=%v ", len(intChan), cap(intChan)) //channel len= 3 cap=3 //5. 从管道中读取数据 var num2 int num2 = <-intChan fmt.Println("num2=", num2) //num2= 211 fmt.Printf("channel len= %v cap=%v ", len(intChan), cap(intChan)) //channel len= 2 cap=3 //6. 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告deadlock(死锁错误) num3 := <-intChan num4 := <-intChan num5 := <-intChan //已经没有了,再取就会报错 //all goroutines are asleep - deadlock! fmt.Println("num3=", num3, "num4=", num4 , "num5=", num5) //num3= 50 num4= 98 }
注意事项
3. 案例
package main import ( "fmt" ) type Cat struct { Name string Age int } func main() { //定义一个存放任意数据类型的管道 3个数据 //var allChan chan interface{} allChan := make(chan interface{}, 3) allChan<- 10 allChan<- "tom jack" cat := Cat{"小花猫", 4} allChan<- cat //我们希望获得到管道中的第三个元素,则先将前2个推出 <-allChan <-allChan newCat := <-allChan //从管道中取出的Cat是什么? fmt.Printf("newCat=%T , newCat=%v ", newCat, newCat) //newCat=main.Cat , newCat={小花猫 4} //下面的写法是错误的!编译不通过 //fmt.Printf("newCat.Name=%v", newCat.Name) //在编译的层面上认为newCat是接口,接口是没有字段的 //使用类型断言 a := newCat.(Cat) fmt.Printf("newCat.Name=%v", a.Name) //newCat.Name=小花猫 }
以上是关于Go_channel(管道)的主要内容,如果未能解决你的问题,请参考以下文章