
1 概念-特性:go 语言channel 是引用类型,goroutine 间通过channel通信,遵循先入先出规则,保证收发数据顺序
2 创建方式:使用make 句柄创建,make(chan 数据类型)
3 向管道发送数据 , 格式如下:
test := make(chan interface{}) //此出不谈容量问题
test <- "hello"
test <- 0
* 发送需要了解的理论知识点:向管道发送数据,如无接受方,发送操作持续阻塞,用户态协成完全由实现方控制,所以需要实现方要写对等代码,有发送方,一定需要有接收方,即使我们的管道是含容量,容量堆满,也终究阻塞,所以有无容量,理论并不矛盾
* 收发不对等报错:fatal error: all goroutines are asleep - deadlock!
4 通过管道接受数据,所涉及知识点如下:
@非阻塞接收(使用该方式接收数据,语句不发生阻塞):
result, ok := <-ch result 接受到的数据,没有数据为0值,引用类型,没有值默认0值, ok 是否接受到数据,bool类型,ch 管道变量
@阻塞接收(使用该方式接收数据,语句会发生阻塞):
result := <-ch
@ 丢弃接受数据,一般为了实现收发对等
<-ch
5 管道数据遍历,格式如下:
for data := range ch {
}
* c 通道不关闭,range 函数就不会结束,到没有接收到任何数据的时间,语句发生阻塞
6 实例代码(只需要关注管道收发业务即可,其它性能监控、数据竞争相关忽略):
package main
import (
"fmt"
"log"
"net/http"
_ "net/http/pprof"
"os"
"runtime"
"sync"
"sync/atomic"
)
var wg sync.WaitGroup
var timers int64
func main() {
runtime.GOMAXPROCS(1) // 限制 CPU 使用数,避免过载
runtime.SetMutexProfileFraction(1) // 开启对锁调用的跟踪
runtime.SetBlockProfileRate(1) // 开启对阻塞操作的跟踪
go func() {
// 开启http服务
if err := http.ListenAndServe(":6060", nil); err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
testChannel()
select {}
}
func testChannel() {
caps := 200000
ch := make(chan int,caps)
wg.Add(caps)
for i:= 0; i < caps; i++ {
go func(a int) {
defer wg.Done()
atomic.AddInt64(&timers, 1)
//原子安全读
if atomic.LoadInt64(&timers) == int64(caps) {
log.Println("close ch========")
defer close(ch)
}
log.Println("索引=",a)
// 通过通道通知main的goroutine
ch <- a
fmt.Println("exit goroutine=",a)
}(i)
}
// 接收数据
for data := range ch {
fmt.Println("channel data = ",data)
}
wg.Wait()
fmt.Println("all done")
}
* 如有错欢迎留言批评指正