国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

GO語(yǔ)言網(wǎng)絡(luò)編程(并發(fā)編程)Channel

這篇具有很好參考價(jià)值的文章主要介紹了GO語(yǔ)言網(wǎng)絡(luò)編程(并發(fā)編程)Channel。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

GO語(yǔ)言網(wǎng)絡(luò)編程(并發(fā)編程)Channel

1、Channel

1.1.1 Channel

單純地將函數(shù)并發(fā)執(zhí)行是沒(méi)有意義的。函數(shù)與函數(shù)間需要交換數(shù)據(jù)才能體現(xiàn)并發(fā)執(zhí)行函數(shù)的意義。

雖然可以使用共享內(nèi)存進(jìn)行數(shù)據(jù)交換,但是共享內(nèi)存在不同的goroutine中容易發(fā)生競(jìng)態(tài)問(wèn)題。為了保證數(shù)據(jù)交換的正確性,必須使用互斥量對(duì)內(nèi)存進(jìn)行加鎖,這種做法勢(shì)必造成性能問(wèn)題。

Go語(yǔ)言的并發(fā)模型是CSP(Communicating Sequential Processes),提倡通過(guò)通信共享內(nèi)存而不是通過(guò)共享內(nèi)存而實(shí)現(xiàn)通信。

如果說(shuō)goroutine是Go程序并發(fā)的執(zhí)行體,channel就是它們之間的連接。channel是可以讓一個(gè)goroutine發(fā)送特定值到另一個(gè)goroutine的通信機(jī)制。

Go 語(yǔ)言中的通道(channel)是一種特殊的類型。通道像一個(gè)傳送帶或者隊(duì)列,總是遵循先入先出(First In First Out)的規(guī)則,保證收發(fā)數(shù)據(jù)的順序。每一個(gè)通道都是一個(gè)具體類型的導(dǎo)管,也就是聲明channel的時(shí)候需要為其指定元素類型。

1.1.2 channel類型

channel是一種類型,一種引用類型。聲明通道類型的格式如下:

var 變量 chan 元素類型

舉幾個(gè)例子:

    var ch1 chan int   // 聲明一個(gè)傳遞整型的通道
    var ch2 chan bool  // 聲明一個(gè)傳遞布爾型的通道
    var ch3 chan []int // 聲明一個(gè)傳遞int切片的通道

1.1.3. 創(chuàng)建channel

通道是引用類型,通道類型的空值是nil。

var ch chan int
fmt.Println(ch) // <nil>

聲明的通道后需要使用make函數(shù)初始化之后才能使用。

創(chuàng)建channel的格式如下:

make(chan 元素類型, [緩沖大小])

channel的緩沖大小是可選的。

舉幾個(gè)例子:

ch4 := make(chan int)
ch5 := make(chan bool)
ch6 := make(chan []int)

1.1.4 channel操作

通道有發(fā)送(send)、接收(receive)和關(guān)閉(close)三種操作。

發(fā)送和接收都使用<-符號(hào)。

現(xiàn)在我們先使用以下語(yǔ)句定義一個(gè)通道:

ch := make(chan int)

發(fā)送
將一個(gè)值發(fā)送到通道中。

ch <- 10 // 把10發(fā)送到ch中

接收
從一個(gè)通道中接收值。

x := <- ch // 從ch中接收值并賦值給變量x
<-ch       // 從ch中接收值,忽略結(jié)果

關(guān)閉
我們通過(guò)調(diào)用內(nèi)置的close函數(shù)來(lái)關(guān)閉通道。

close(ch)

關(guān)于關(guān)閉通道需要注意的事情是,只有在通知接收方goroutine所有的數(shù)據(jù)都發(fā)送完畢的時(shí)候才需要關(guān)閉通道。通道是可以被垃圾回收機(jī)制回收的,它和關(guān)閉文件是不一樣的,在結(jié)束操作之后關(guān)閉文件是必須要做的,但關(guān)閉通道不是必須的。

關(guān)閉后的通道有以下特點(diǎn):

    1.對(duì)一個(gè)關(guān)閉的通道再發(fā)送值就會(huì)導(dǎo)致panic。
    2.對(duì)一個(gè)關(guān)閉的通道進(jìn)行接收會(huì)一直獲取值直到通道為空。
    3.對(duì)一個(gè)關(guān)閉的并且沒(méi)有值的通道執(zhí)行接收操作會(huì)得到對(duì)應(yīng)類型的零值。
    4.關(guān)閉一個(gè)已經(jīng)關(guān)閉的通道會(huì)導(dǎo)致panic。

1.1.5 無(wú)緩沖的通道

GO語(yǔ)言網(wǎng)絡(luò)編程(并發(fā)編程)Channel,GO,網(wǎng)絡(luò),golang,服務(wù)器
無(wú)緩沖的通道又稱為阻塞的通道。我們來(lái)看一下下面的代碼:

func main() {
    ch := make(chan int)
    ch <- 10
    fmt.Println("發(fā)送成功")
}

上面這段代碼能夠通過(guò)編譯,但是執(zhí)行的時(shí)候會(huì)出現(xiàn)以下錯(cuò)誤:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
        .../src/github.com/pprof/studygo/day06/channel02/main.go:8 +0x54

為什么會(huì)出現(xiàn)deadlock錯(cuò)誤呢?

因?yàn)槲覀兪褂胏h := make(chan int)創(chuàng)建的是無(wú)緩沖的通道,無(wú)緩沖的通道只有在有人接收值的時(shí)候才能發(fā)送值。就像你住的小區(qū)沒(méi)有快遞柜和代收點(diǎn),快遞員給你打電話必須要把這個(gè)物品送到你的手中,簡(jiǎn)單來(lái)說(shuō)就是無(wú)緩沖的通道必須有接收才能發(fā)送。

上面的代碼會(huì)阻塞在ch <- 10這一行代碼形成死鎖,那如何解決這個(gè)問(wèn)題呢?

一種方法是啟用一個(gè)goroutine去接收值,例如:

func recv(c chan int) {
    ret := <-c
    fmt.Println("接收成功", ret)
}
func main() {
    ch := make(chan int)
    go recv(ch) // 啟用goroutine從通道接收值
    ch <- 10
    fmt.Println("發(fā)送成功")
}

無(wú)緩沖通道上的發(fā)送操作會(huì)阻塞,直到另一個(gè)goroutine在該通道上執(zhí)行接收操作,這時(shí)值才能發(fā)送成功,兩個(gè)goroutine將繼續(xù)執(zhí)行。相反,如果接收操作先執(zhí)行,接收方的goroutine將阻塞,直到另一個(gè)goroutine在該通道上發(fā)送一個(gè)值。

使用無(wú)緩沖通道進(jìn)行通信將導(dǎo)致發(fā)送和接收的goroutine同步化。因此,無(wú)緩沖通道也被稱為同步通道。

1.1.6 有緩沖的通道

解決上面問(wèn)題的方法還有一種就是使用有緩沖區(qū)的通道。

GO語(yǔ)言網(wǎng)絡(luò)編程(并發(fā)編程)Channel,GO,網(wǎng)絡(luò),golang,服務(wù)器
我們可以在使用make函數(shù)初始化通道的時(shí)候?yàn)槠渲付ㄍǖ赖娜萘?,例如?/p>

func main() {
    ch := make(chan int, 1) // 創(chuàng)建一個(gè)容量為1的有緩沖區(qū)通道
    ch <- 10
    fmt.Println("發(fā)送成功")
}

只要通道的容量大于零,那么該通道就是有緩沖的通道,通道的容量表示通道中能存放元素的數(shù)量。就像你小區(qū)的快遞柜只有那么個(gè)多格子,格子滿了就裝不下了,就阻塞了,等到別人取走一個(gè)快遞員就能往里面放一個(gè)。

我們可以使用內(nèi)置的len函數(shù)獲取通道內(nèi)元素的數(shù)量,使用cap函數(shù)獲取通道的容量,雖然我們很少會(huì)這么做。

1.1.7

可以通過(guò)內(nèi)置的close()函數(shù)關(guān)閉channel(如果你的管道不往里存值或者取值的時(shí)候一定記得關(guān)閉管道)

package main

import "fmt"

func main() {
    c := make(chan int)
    go func() {
        for i := 0; i < 5; i++ {
            c <- i
        }
        close(c)
    }()
    for {
        if data, ok := <-c; ok {
            fmt.Println(data)
        } else {
            break
        }
    }
    fmt.Println("main結(jié)束")
}

1.1.8 如何優(yōu)雅的從通道循環(huán)取值

當(dāng)通過(guò)通道發(fā)送有限的數(shù)據(jù)時(shí),我們可以通過(guò)close函數(shù)關(guān)閉通道來(lái)告知從該通道接收值的goroutine停止等待。當(dāng)通道被關(guān)閉時(shí),往該通道發(fā)送值會(huì)引發(fā)panic,從該通道里接收的值一直都是類型零值。那如何判斷一個(gè)通道是否被關(guān)閉了呢?

我們來(lái)看下面這個(gè)例子:

// channel 練習(xí)
func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    // 開(kāi)啟goroutine將0~100的數(shù)發(fā)送到ch1中
    go func() {
        for i := 0; i < 100; i++ {
            ch1 <- i
        }
        close(ch1)
    }()
    // 開(kāi)啟goroutine從ch1中接收值,并將該值的平方發(fā)送到ch2中
    go func() {
        for {
            i, ok := <-ch1 // 通道關(guān)閉后再取值ok=false
            if !ok {
                break
            }
            ch2 <- i * i
        }
        close(ch2)
    }()
    // 在主goroutine中從ch2中接收值打印
    for i := range ch2 { // 通道關(guān)閉后會(huì)退出for range循環(huán)
        fmt.Println(i)
    }
}

從上面的例子中我們看到有兩種方式在接收值的時(shí)候判斷通道是否被關(guān)閉,我們通常使用的是for range的方式。

1.1.9單向通道

有的時(shí)候我們會(huì)將通道作為參數(shù)在多個(gè)任務(wù)函數(shù)間傳遞,很多時(shí)候我們?cè)诓煌娜蝿?wù)函數(shù)中使用通道都會(huì)對(duì)其進(jìn)行限制,比如限制通道在函數(shù)中只能發(fā)送或只能接收。

Go語(yǔ)言中提供了單向通道來(lái)處理這種情況。例如,我們把上面的例子改造如下:

func counter(out chan<- int) {
    for i := 0; i < 100; i++ {
        out <- i
    }
    close(out)
}

func squarer(out chan<- int, in <-chan int) {
    for i := range in {
        out <- i * i
    }
    close(out)
}
func printer(in <-chan int) {
    for i := range in {
        fmt.Println(i)
    }
}

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go counter(ch1)
    go squarer(ch2, ch1)
    printer(ch2)
}

其中,

1.chan<- int是一個(gè)只能發(fā)送的通道,可以發(fā)送但是不能接收;
2.<-chan int是一個(gè)只能接收的通道,可以接收但是不能發(fā)送。

在函數(shù)傳參及任何賦值操作中將雙向通道轉(zhuǎn)換為單向通道是可以的,但反過(guò)來(lái)是不可以的。

1.1.10 通道總結(jié)

channel常見(jiàn)的異常總結(jié),如下圖:

GO語(yǔ)言網(wǎng)絡(luò)編程(并發(fā)編程)Channel,GO,網(wǎng)絡(luò),golang,服務(wù)器
注意:關(guān)閉已經(jīng)關(guān)閉的channel也會(huì)引發(fā)panic。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-707730.html

到了這里,關(guān)于GO語(yǔ)言網(wǎng)絡(luò)編程(并發(fā)編程)Channel的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Go語(yǔ)言網(wǎng)絡(luò)編程(socket編程)WebSocket編程

    WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議 WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù) 在WebSocket API中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸 需要安裝第

    2024年02月09日
    瀏覽(93)
  • Go語(yǔ)言網(wǎng)絡(luò)編程(socket編程)TCP

    TCP協(xié)議 TCP/IP(Transmission Control Protocol/Internet Protocol) 即傳輸控制協(xié)議/網(wǎng)間協(xié)議,是一種面向連接(連接導(dǎo)向)的、可靠的、基于字節(jié)流的傳輸層(Transport layer)通信協(xié)議,因?yàn)槭敲嫦蜻B接的協(xié)議,數(shù)據(jù)像水流一樣傳輸,會(huì)存在黏包問(wèn)題。 TCP服務(wù)端 一個(gè)TCP服務(wù)端可以同時(shí)連接很

    2024年02月09日
    瀏覽(97)
  • Go語(yǔ)言網(wǎng)絡(luò)編程(socket編程)TCP粘包

    服務(wù)端代碼如下: 客戶端代碼如下: 將上面的代碼保存后,分別編譯。先啟動(dòng)服務(wù)端再啟動(dòng)客戶端,可以看到服務(wù)端輸出結(jié)果如下: 收到client發(fā)來(lái)的數(shù)據(jù): Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you? 收到client發(fā)來(lái)的數(shù)

    2024年02月09日
    瀏覽(96)
  • Go語(yǔ)言網(wǎng)絡(luò)編程介紹以及案例運(yùn)用

    1. 基本概念 TCP 和 UDP : Go語(yǔ)言支持TCP(傳輸控制協(xié)議)和UDP(用戶數(shù)據(jù)報(bào)協(xié)議)。TCP提供可靠的、面向連接的通信,而UDP提供無(wú)連接的快速數(shù)據(jù)傳輸。 并發(fā) : Go語(yǔ)言的并發(fā)模型是通過(guò)goroutines實(shí)現(xiàn)的。每個(gè)網(wǎng)絡(luò)請(qǐng)求都可以在自己的goroutine中處理,實(shí)現(xiàn)高效的并發(fā)。 Channels : 用于

    2024年01月25日
    瀏覽(105)
  • Go語(yǔ)言的網(wǎng)絡(luò)編程與HTTP服務(wù)

    Go語(yǔ)言(Golang)是Google開(kāi)發(fā)的一種靜態(tài)類型、垃圾回收、并發(fā)簡(jiǎn)單的編程語(yǔ)言。Go語(yǔ)言的設(shè)計(jì)目標(biāo)是讓程序員更容易編寫(xiě)并發(fā)程序,并在多核處理器上充分發(fā)揮性能。Go語(yǔ)言的網(wǎng)絡(luò)編程和HTTP服務(wù)是其核心功能之一,可以輕松地構(gòu)建高性能、可擴(kuò)展的網(wǎng)絡(luò)應(yīng)用程序。 在本文中,我們

    2024年02月19日
    瀏覽(100)
  • Go語(yǔ)言實(shí)戰(zhàn):網(wǎng)絡(luò)編程與TCP_UDP

    Go語(yǔ)言是一種現(xiàn)代的編程語(yǔ)言,由Google的Robert Griesemer、Rob Pike和Ken Thompson于2009年開(kāi)發(fā)。Go語(yǔ)言的設(shè)計(jì)目標(biāo)是簡(jiǎn)單、高效、可擴(kuò)展和易于使用。它具有垃圾回收、類型安全、并發(fā)性能等優(yōu)點(diǎn)。Go語(yǔ)言的網(wǎng)絡(luò)編程庫(kù) net 包提供了TCP/UDP的實(shí)現(xiàn),使得開(kāi)發(fā)者可以輕松地編寫(xiě)網(wǎng)絡(luò)應(yīng)用程序

    2024年02月21日
    瀏覽(96)
  • Go語(yǔ)言的網(wǎng)絡(luò)編程與TCP_IP

    Go語(yǔ)言是一種現(xiàn)代的編程語(yǔ)言,由Google的Robert Griesemer、Rob Pike和Ken Thompson在2009年開(kāi)發(fā)。Go語(yǔ)言的設(shè)計(jì)目標(biāo)是簡(jiǎn)單、高效、可擴(kuò)展和易于使用。它具有弱類型、垃圾回收、并發(fā)性和原生支持的網(wǎng)絡(luò)編程。Go語(yǔ)言的網(wǎng)絡(luò)編程是其強(qiáng)大功能之一,它使得開(kāi)發(fā)者可以輕松地編寫(xiě)高性能的

    2024年02月22日
    瀏覽(115)
  • 多進(jìn)程并發(fā)TCP服務(wù)器模型(含客戶端)(網(wǎng)絡(luò)編程 C語(yǔ)言實(shí)現(xiàn))

    摘要 :大家都知道不同pc間的通信需要用到套接字sockte來(lái)實(shí)現(xiàn),但是服務(wù)器一次只能收到一個(gè)客戶端發(fā)來(lái)的消息,所以為了能讓服務(wù)器可以接收多個(gè)客戶端的連接與消息的傳遞,我們就引入了多進(jìn)程并發(fā)這樣一個(gè)概念。聽(tīng)名字就可以知道--需要用到進(jìn)程,當(dāng)然也有多線程并發(fā)

    2024年02月17日
    瀏覽(105)
  • Go并發(fā)編程 Goroutine、Channel、Select、Mutex鎖、sync、Atomic等

    Go并發(fā)編程 Goroutine、Channel、Select、Mutex鎖、sync、Atomic等

    本文所有實(shí)例代碼運(yùn)行g(shù)o版本: go version go1.18.10 windows/amd64 串行:所有任務(wù)一件一件做,按照事先的順序依次執(zhí)行,沒(méi)有被執(zhí)行到的任務(wù)只能等待。最終執(zhí)行完的時(shí)間等于各個(gè)子任務(wù)之和。 并發(fā):是以交替的方式利用 等待 某個(gè)任務(wù)的時(shí)間來(lái)處理其他任務(wù)計(jì)算邏輯,在計(jì)算機(jī)

    2024年02月07日
    瀏覽(22)
  • Go語(yǔ)言網(wǎng)絡(luò)編程:HTTP服務(wù)端之底層原理與源碼分析——http.HandleFunc()、http.ListenAndServe()

    Go語(yǔ)言網(wǎng)絡(luò)編程:HTTP服務(wù)端之底層原理與源碼分析——http.HandleFunc()、http.ListenAndServe()

    在 Golang只需要幾行代碼便能啟動(dòng)一個(gè) http 服務(wù),在上述代碼中,完成了兩件事: 調(diào)用 http.HandleFunc 方法,注冊(cè)了對(duì)應(yīng)于請(qǐng)求路徑 /ping 的 handler 函數(shù) 調(diào)用 http.ListenAndServe,啟動(dòng)了一個(gè)端口為 8999 的 http 服務(wù) 2.1 server 結(jié)構(gòu) Addr :表示服務(wù)器監(jiān)聽(tīng)的地址。如\\\":8080\\\"表示服務(wù)器在本地

    2024年02月08日
    瀏覽(96)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包