欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語言通道之無緩沖通道

 更新時間:2022年07月16日 09:11:41   作者:奮斗的大橙子  
這篇文章介紹了Go語言通道之無緩沖通道,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、通道是什么?

其實無論是原子函數(shù)還是共享鎖都是通過共享內(nèi)存的方式進行的同步、效率一般不高,而Go語言中則使用了通道,它是一種通過傳遞信息的方式進行數(shù)據(jù)同步,通過發(fā)送和接收需要共享的資源,在goroutine 之間做同步??梢园淹ǖ揽醋魇荊oroutine之間的橋梁。

例1:創(chuàng)建一個通道

// 無緩沖的整型通道
unbuffered := make(chan int)
// 有緩沖的字符串通道
buffered := make(chan string, 10)

通道分為有緩沖和無緩沖的通道。

創(chuàng)建一個Channel的關(guān)鍵點:1.使用make創(chuàng)建 2.使用chan來告訴make我要創(chuàng)建的是通道 3.要告訴通道我要建立什么類型的通道。

例2:向通道發(fā)送值和接受值

// 有緩沖的字符串通道
buffered := make(chan string, 10)
// 通過通道發(fā)送一個字符串
buffered <- "Gopher"
// 從通道接收一個字符串
value := <-buffered

這個例子中創(chuàng)建了一個string類型的Channel,并向通道內(nèi)傳遞了一個“Gopher”字符串,這里是通過<-進行傳入的,然后通過<-這個方式把值放到value當中。

這里我的理解 <-就好比是一個賦值符號,無論是把值傳遞到Channel中,還是把Channel中的值傳出來,都是將右邊的值給左邊

二、通道的種類

由上面的例如1,可以看到Channel也是有多種的,分為無緩沖通道和有緩沖通道,下面就簡單總結(jié)一下兩種類型的通道。

1.無緩沖通道

無緩沖的通道(unbuffered channel)是指在接收前沒有能力保存任何值的通道。這種類型的通道要求發(fā)送goroutine 和接收goroutine 同時準備好,才能完成發(fā)送和接收操作。

上面的圖很好的解釋了通道和Goroutine的關(guān)系

  • 1.左右兩個goroutine都沒有將手放到通道中。
  • 2.左邊的Goroutine將手放到了通道中,模擬了將數(shù)據(jù)放入通道,此時goroutine會被鎖住
  • 3.右邊的Goroutine也將手放到了通道中,模擬了從通道中取出數(shù)據(jù),同樣進入了通道也會被鎖住
  • 4.兩者通過通道執(zhí)行數(shù)據(jù)的交換
  • 5.交換完成
  • 6.兩者將手從通道中拿出,模擬了被鎖住的goroutine被釋放

下面這個程序,模擬了兩個人打網(wǎng)球,很好的模擬了兩個協(xié)程間通過channel進行數(shù)據(jù)交換

package ChannelDemo

import (
  "fmt"
  "math/rand"
  "sync"
  "time"
)

var wg sync.WaitGroup

func init() {
    rand.Seed(time.Now().UnixNano())
}

func PlayTennis() {
    court := make(chan int)
    wg.Add(2)
    //啟動了兩個協(xié)程,一個納達爾一個德約科維奇
    go player("納達爾", court)
    go player("德約科維奇", court)

    //將1放到通道中,模擬開球
    court <- 1
    wg.Wait()
}

func player(name string, court chan int) {
    defer wg.Done()
    for {
        // 將數(shù)據(jù)從通道中取出
        ball, ok := <-court
        if !ok {
            fmt.Printf("選手 %s 勝利\n", name)
            return
        }

        //獲取一個隨機值,如果可以整除13,就讓一個人沒有擊中,進而關(guān)閉整個通道
        n := rand.Intn(100)
        if n%13 == 0 {
            fmt.Printf("選手 %s 沒接到\n", name)
            close(court)
            return
        }
        //如果擊中球,就將擊球的數(shù)量+1,放回通道中
        fmt.Printf("選手 %s 擊中 %d\n", name, ball)
        ball++
        court <- ball
    }
}

執(zhí)行結(jié)果(每次會有變化):

選手 納達爾 擊中 1
選手 德約科維奇 擊中 2
選手 納達爾 擊中 3
選手 德約科維奇 擊中 4
選手 納達爾 擊中 5
選手 德約科維奇 擊中 6
選手 納達爾 擊中 7
選手 德約科維奇 擊中 8
選手 納達爾 沒接到
選手 德約科維奇 勝利

ok 標志是否為false。如果這個值是false,表示通道已經(jīng)被關(guān)閉,游戲結(jié)束。

下面這個例子,模擬里一個接力賽,也就是協(xié)程之間的傳遞的另一種形式

package ChannelDemo

import (
    "fmt"
    "sync"
    "time"
)

var runnerWg sync.WaitGroup

func Running() {
    //創(chuàng)建一個“接力棒”,也就是通道
    baton := make(chan int)
    runnerWg.Add(1)
    //創(chuàng)建第一個跑步走
    go Runner(baton)
    //開始跑
    baton <- 1
    runnerWg.Wait()
}

func Runner(baton chan int) {
    var newRunner int

    //選手接過接力棒
    runner := <-baton
    fmt.Printf("第 %d 選手接棒 \n", runner)

    //如果不是第四名選手,那么說明比賽還在繼續(xù)
    if runner != 4 {
        //創(chuàng)建一名新選手
        newRunner = runner + 1
        fmt.Printf("第 %d 準備接棒 \n", newRunner)
        go Runner(baton)
    }

    //模擬跑步
    time.Sleep(100 * time.Millisecond)
    //如果第四名跑完了,就結(jié)束
    if runner == 4 {
        fmt.Printf("第 %d 結(jié)束賽跑 \n", runner)
        runnerWg.Done()
        return
    }

    fmt.Printf("第 %d 選手和第 %d 選手交換了接力棒 \n",
        runner,
        newRunner)

    //選手遞出接力棒
    baton <- newRunner
}

運行結(jié)果:

第 1 名選手接棒
第 2 名選手準備接棒
第 1 名選手將接力棒遞給第 2 名選手
第 2 名選手接棒
第 3 名選手準備接棒
第 2 名選手將接力棒遞給第 3 名選手
第 3 名選手接棒
第 4 名選手準備接棒
第 3 名選手將接力棒遞給第 4 名選手
第 4 名選手接棒
第 4 名選手沖線,比賽結(jié)束 

三、無緩沖通道小結(jié)

我在看例子的過程中,其實遇到的問題在于,我沒有理解goroutine是怎么進行交換的,我以為是goroutine有一個集合一樣的結(jié)構(gòu)在通道外面等待取數(shù)據(jù),這樣就存在我剛拿完再那的情況。就像下面這個圖顯示一樣

但是實際情況應(yīng)該像下面

Go1寫入通道鎖住的Go1、Go2讀出進入通道鎖住Go2,只有Go1寫完Go2取完才能釋放,但是像上面第一個例子代碼,讀出之后馬上就寫入,所以對于這樣的協(xié)程其實一直是鎖住的狀態(tài)。兩個協(xié)程就通過這種方式進行數(shù)據(jù)的傳遞。

到此這篇關(guān)于Go語言通道之無緩沖通道的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 一文帶你深入了解Go語言中的事務(wù)

    一文帶你深入了解Go語言中的事務(wù)

    事務(wù)中止時,你結(jié)束事務(wù)了嗎?在開發(fā)時有可能就會犯這樣的錯誤,其問題就是你在提交事務(wù)時,如果中間有其他業(yè)務(wù)就取消操作,那么事務(wù)也關(guān)閉了嗎?本文就來詳細講講
    2023-04-04
  • Golang利用casbin實現(xiàn)權(quán)限驗證詳解

    Golang利用casbin實現(xiàn)權(quán)限驗證詳解

    Casbin是一個強大的、高效的開源訪問控制框架,其權(quán)限管理機制支持多種訪問控制模型,Casbin只負責訪問控制。本文將利用casbin實現(xiàn)權(quán)限驗證功能,需要的可以參考一下
    2023-02-02
  • 詳解minio分布式文件存儲

    詳解minio分布式文件存儲

    MinIO 是一款基于 Go 語言的高性能、可擴展、云原生支持、操作簡單、開源的分布式對象存儲產(chǎn)品,這篇文章主要介紹了minio分布式文件存儲,需要的朋友可以參考下
    2023-10-10
  • golang簡單獲取上傳文件大小的實現(xiàn)代碼

    golang簡單獲取上傳文件大小的實現(xiàn)代碼

    這篇文章主要介紹了golang簡單獲取上傳文件大小的方法,涉及Go語言文件傳輸及文件屬性操作的相關(guān)技巧,需要的朋友可以參考下
    2016-07-07
  • golang之數(shù)據(jù)校驗的實現(xiàn)代碼示例

    golang之數(shù)據(jù)校驗的實現(xiàn)代碼示例

    這篇文章主要介紹了golang之數(shù)據(jù)校檢的實現(xiàn)代碼示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • go語言中切片與內(nèi)存復(fù)制 memcpy 的實現(xiàn)操作

    go語言中切片與內(nèi)存復(fù)制 memcpy 的實現(xiàn)操作

    這篇文章主要介紹了go語言中切片與內(nèi)存復(fù)制 memcpy 的實現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go中的nil切片和空切片區(qū)別詳解

    Go中的nil切片和空切片區(qū)別詳解

    這篇文章主要介紹了Go中的nil切片和空切片區(qū)別詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Go語言讀取YAML 配置文件的兩種方式分享

    Go語言讀取YAML 配置文件的兩種方式分享

    在日常開發(fā)中,YAML 格式的文件基本上被默認為是配置文件,其內(nèi)容因為縮進帶來的層級感看起來非常直觀和整潔。本文分享了讀取YAML 配置文件的兩種方式,需要的可以參考一下
    2022-12-12
  • 詳解GO語言中[]byte與string的兩種轉(zhuǎn)換方式和底層實現(xiàn)

    詳解GO語言中[]byte與string的兩種轉(zhuǎn)換方式和底層實現(xiàn)

    這篇文章主要為大家詳細介紹了GO語言中[]byte與string的兩種轉(zhuǎn)換方式和底層實現(xiàn)的相關(guān)知識,文中的示例代碼講解詳細,有需要的小伙伴可以參考下
    2024-03-03
  • GO語言中Chan實現(xiàn)原理的示例詳解

    GO語言中Chan實現(xiàn)原理的示例詳解

    這篇文章主要為大家詳細介紹了Go語言中Chan實現(xiàn)原理的相關(guān)資料,文中的示例代碼講解詳細,對我們學(xué)習(xí)Go語言有一定的幫助,需要的可以參考一下
    2023-02-02

最新評論