Go学习笔记—Channel通道
生活随笔
收集整理的這篇文章主要介紹了
Go学习笔记—Channel通道
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Go并發通信——Channel
? Go語言的并發模型是CSP(Communicating Sequential Processes),提倡通過通信共享內存而不是通過共享內存而實現通信。(DO NOT COMMUNICATE BY SHARING MEMORY; INSTEAD, SHARE MEMORY BY COMMUNICATING.)
? 如果說goroutine是Go程序并發的執行體,channel就是它們之間的連接。channel是可以讓一個goroutine發送特定值到另一個goroutine的通信機制。
? Go 語言中的通道(channel)是一種特殊的類型。通道像一個傳送帶或者隊列,總是遵循先入先出(First In First Out)的規則,保證收發數據的順序。每一個通道都是一個具體類型的導管,也就是聲明channel的時候需要為其指定元素類型。
通道Channel
1. channel—注意點
2. channel—基礎操作
ch <- 10 //10存入通道 x := <- ch //通道中取出第一個值賦給x <- ch //取出值,忽略結果 close(ch) //關閉通道( 通道會被垃圾回收機制回收,不一定非要關閉 ) //************************************************************************************** select{ //類似于switch,哪個條件滿足就會執行哪個,多個滿足則隨機執行一個,沒有滿足則阻塞等待case <-ch1:...case data := <-ch2:...case ch3<-data:...default:默認操作 }//select實現通知退出機制 func dosth(done chan struct{}) chan int {ch := make(chan int)go func() {Label:for {select {case ch <- rand.Int():case <-done: 接收到done信號停止運行break Label}}close(ch)}()return ch } func main() {done := make(chan struct{})ch := dosth(done)fmt.Println(<-ch)fmt.Println(<-ch)done <- struct{}{}fmt.Println(<-ch) }//************************************************************************************** for v := range in { //for range 進行通道讀取,只有當in關閉時,才會終止循環out <- v + 1 } close(out)3. channel—無緩沖通道 VS 有緩沖通道
(1)無緩沖通道
(2)有緩沖通道
| 獲取通道元素數量 | len(channel) |
| 獲取通道容量 | cap(channel) |
(3)單向通道(在賦值或者傳參時,我們將其設為單向通道,使得該函數只能對其進行讀/寫一個操作)
func squarer(out chan<- int, in <-chan int) {for i := range in {out <- i * i}close(out) }4. channel—用例
(1)實現管道
//一個函數的輸入參數和輸出參數是相同的chan類型,則函數可以調用自己,形成一個調用鏈 func chain(in chan int) chan int { //作用是將輸入的通道值加一out := make(chan int)go func() {for v := range in { //由于in,out聲明的都是無緩沖,所以每讀一個都會阻塞,等下一個參數out <- v + 1}close(out)}()return out }func Guandao() {in := make(chan int)go func() {for i := 0; i < 10; i++ { //初始化輸入參數in <- i}close(in)}()out := chain(chain(chain(in))) //疊加形成管道for v := range out { //從最終的輸出通道讀出結果fmt.Println(v)} }(2)實現每個事務一個goroutine
//通過設置任務通道,每當有新任務來臨時,為其分配相應的goroutine進行執行 type task struct {num int }func (t *task) job(wait sync.WaitGroup) {fmt.Println("i am", t.num, "WORKING")time.Sleep(3 * time.Second) //模擬工作流程fmt.Println("i am", t.num, "DONE")wait.Done() //工作完成,wait-1 }func AllocateJob() {wait := sync.WaitGroup{} //wait防止程序未執行完成就退出taskchan := make(chan *task, 10) //接收任務通道go func() {for i := 1; i <= 10; i++ { //模擬有新工作加入,1秒加入一個task := &task{num: i}wait.Add(1) //wait+1time.Sleep(1 * time.Second)taskchan <- task //任務加入任務通道}}()go func() {for task := range taskchan { //從通道中取出任務,并分配goroutine執行go task.job(wait)}}()wait.Wait() }(3)實現future模式
? 適用于一個流程中需要調用多個子調用的情況,并且這些子調用之間沒有依賴。future模式的優勢就是將其同步調用轉化為異步調用。
//通過通道,實現在執行一個較為耗時的任務時,先通過goroutine調用該任務,由chan傳入參數后,并行做其他的事,最后再通過通道獲取其運行的結果。 type query struct {in chan stringout chan string }func doquery(q query) {in := <-q.intime.Sleep(5 * time.Second) //模擬訪問數據庫進行查詢q.out <- in + "的結果"}func Futuretest() {temp := query{in: make(chan string), out: make(chan string)}go doquery(temp)temp.in <- "select * from user"time.Sleep(3 * time.Second) //模擬在進行數據庫查詢時,我們可以做一些其他的事情fmt.Println(<-temp.out) //做完其他的事情,并且數據庫查詢也完成了,我們從通道中獲取查詢結果 }總結
以上是生活随笔為你收集整理的Go学习笔记—Channel通道的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android学习日记13--数据存储之
- 下一篇: UNP Chapter 22 - 信号驱