通道

channel通道

package main

import "fmt"

//15
func main() {
    /*
    channel
    */

    var a chan int
    fmt.Printf("%T,%v\n",a,a) //chan int,<nil>

    if a == nil {
        fmt.Println("channel是nil的,不能使用,需要先創(chuàng)建通道")
        a = make(chan int)
        fmt.Println(a) //0xc00008c060
    }

    test1(a)

    var ch1 chan bool
    ch1 = make(chan bool)

    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println("子goroutine:",i)
        }
        //循環(huán)結(jié)束,向通道中寫數(shù)據(jù)
        ch1 <- true
        fmt.Println("結(jié)束。。。") //結(jié)束。。。
    }()

    //寫之前讀阻塞,讀之前寫阻塞
    data := <- ch1
    fmt.Println("main data --->",data) //main data ---> true
    fmt.Println("main over") //main over
}

func test1(ch chan int){
    fmt.Printf("%T,%v\n",ch,ch) //chan int,0xc000100060
}

關(guān)閉通道和通道上范圍循環(huán)

package main

import (
    "fmt"
    "time"
)

//16
func main() {
    /*
    關(guān)閉通道:close(ch)
        子groutine,寫出10個(gè)數(shù)據(jù)
            每寫一個(gè),阻塞一次,主goroutine讀取一次,解除阻塞

        主goroutine,讀取數(shù)據(jù)
            每次讀取數(shù)據(jù),阻塞一次,子goroutine,寫出一個(gè),解除阻塞

    */
    ch1 := make(chan int)
    go sendData(ch1)

    //讀取通道的數(shù)據(jù)
    for{
        time.Sleep(1 * time.Second)
        v,ok := <- ch1
        if !ok {
            fmt.Println("已經(jīng)讀取了所有數(shù)據(jù)",v,ok)
            break
        }
        fmt.Println("讀取的數(shù)據(jù):",v,ok)
    }
    fmt.Println("main over")

}

func sendData(ch1 chan int)  {
    //發(fā)送方
    for i := 0; i < 10; i++ {
        ch1 <- i
    }
    close(ch1)
}

package main

import (
    "fmt"
)

//17
func main() {
    /*
    通過(guò)range訪問(wèn)通道
    */
    ch1 := make(chan int)
    go sendData2(ch1)

    //range來(lái)訪問(wèn)通道
    for v := range ch1 {
        fmt.Println("讀取數(shù)據(jù):",v)
    }
    fmt.Println("main over")

}

func sendData2(ch1 chan int)  {
    //發(fā)送方
    for i := 0; i < 10; i++ {
        ch1 <- i
    }
    close(ch1) //通知對(duì)方通道關(guān)閉
}

緩沖通道

package main

import (
    "fmt"
    "strconv"
)

//18
func main() {
    /*
        非緩沖通道:make(chan T)
            一次發(fā)送,一次接受,都是阻塞的
        緩沖通道:make(chan T,capacity)
            發(fā)送:緩沖區(qū)的數(shù)據(jù)滿了,才會(huì)阻塞
            接收:緩沖區(qū)的數(shù)據(jù)空了,才會(huì)阻塞
    */
    ch1 := make(chan int)
    fmt.Println(len(ch1), cap(ch1)) //0 0

    ch2 := make(chan int, 5)
    fmt.Println(len(ch2), cap(ch2)) //0 5

    ch2 <- 100
    fmt.Println(len(ch2), cap(ch2)) //1 5

    ch2 <- 100
    ch2 <- 200
    ch2 <- 300
    ch2 <- 400
    fmt.Println(len(ch2), cap(ch2)) //5 5

    // ch2 <- 600 //fatal error: all goroutines are asleep - deadlock!

    fmt.Println("-------------")
    ch3 := make(chan string, 4)
    go sendData3(ch3)

    for{
        v,ok := <-ch3
        if !ok {
            fmt.Println("讀完了..",ok)
            break
        }
        fmt.Println("\t讀取的數(shù)據(jù)是:",v)
    }
    fmt.Println("main over...")

}

func sendData3(ch chan string){
    for i := 0; i < 10; i++ {
        ch <- "數(shù)據(jù)" + strconv.Itoa(i)
        fmt.Println("子goroutine中寫出第 %d 個(gè)數(shù)據(jù)\n",i)
    }
    close(ch)
}

定向通道

package main

import "fmt"

//19
func main() {
    /*
        雙向通道
            chan T
                chan <- data,發(fā)送數(shù)據(jù),寫出
                data <- chan,獲取數(shù)據(jù),讀取

        單向:定向
            chan <- T,只支持寫操作
            <- chan T,只讀
    */
    ch1 := make(chan string)
    done := make(chan bool)
    go sendData4(ch1, done)

    data := <- ch1
    fmt.Println("子goroutine傳來(lái):",data) //子goroutine傳來(lái): isuntong

    ch1 <- "isuntong2"

    <- done //不通知不要結(jié)束
    fmt.Println("main over...")

}

func sendData4(ch1 chan string, done chan bool) {
    ch1 <- "isuntong"

    data := <- ch1
    fmt.Println("main goroutine傳來(lái):",data)

    done <- true
}

package main

import "fmt"

//20
func main() {
    /*
        單向:定向
            chan <- T,只支持寫操作
            <- chan T,只讀

    用作默寫函數(shù)保護(hù)
    函數(shù)內(nèi)部對(duì)于ch1只能讀,不能寫,所以可以保護(hù)安全

    創(chuàng)建雙向channel,在某些函數(shù)中限定只讀只寫,作為保護(hù)。

    */
    ch1 := make(chan int) //雙向,讀寫
    //ch2 := make(chan <- int) //單向,只能寫
    //ch3 := make(<- chan int) //單向,只能讀

    // ch2 <- 1000
    // data := <-ch2 //invalid operation: <-ch2 (receive from send-only type chan<- int)

    // data := <- ch3
    // ch3 <- 2000 //invalid operation: ch3 <- 2000 (send to receive-only type <-chan int)
    // fmt.Println(data)

    go fun3(ch1) //可讀可寫
    // fun3(ch2)

    data2 := <- ch1
    fmt.Println("fun3函數(shù)寫出的數(shù)據(jù)是:",data2) //fun3函數(shù)寫出的數(shù)據(jù)是: 100

}

//該函數(shù),只能操作只寫的通道
func fun3(ch chan <- int) {
    ch <- 100
    fmt.Println("fun3函數(shù)結(jié)束") //fun3函數(shù)結(jié)束
}

func fun4(ch <- chan int) {

    fmt.Println("fun3函數(shù)結(jié)束") //fun3函數(shù)結(jié)束
}

time包中的通道相關(guān)函數(shù)

package main

import (
    "fmt"
    "time"
)

//21
func main() {
    /*
        1. func NewTimer(d Duration) *Timer
            創(chuàng)建一個(gè)計(jì)數(shù)器,d時(shí)間以后觸發(fā)

        2. func After(d Duration) <- chan Time
            返回一個(gè)通道,存儲(chǔ)的是d時(shí)間間隔之后的當(dāng)前時(shí)間

    */
    timer := time.NewTimer(3 * time.Second)
    fmt.Printf("%T\n",timer) //*time.Timer
    fmt.Println(time.Now()) //2020-03-26 19:29:30.612334 +0800 CST m=+0.000112607

    //此處等待channel中的數(shù)據(jù),會(huì)阻塞3秒
    ch2 := timer.C
    fmt.Println(<-ch2) //2020-03-26 19:29:33.614302 +0800 CST m=+3.002032115

    //新建一個(gè)計(jì)數(shù)器
    timer2 := time.NewTimer(5 * time.Second)
    //開(kāi)始goroutine,來(lái)處理觸發(fā)后的事件
    go func() {
        <- timer2.C
        fmt.Println("Timer2結(jié)束")
    }()

    time.Sleep(3 * time.Second)
    flag := timer2.Stop() //停止定時(shí)
    if flag {
        fmt.Println("Timer2停止了")
    }


    //After(d Duration)
    ch := time.After(3 * time.Second)
    fmt.Printf("%T\n",ch) //<-chan time.Time
    fmt.Println(time.Now()) //2020-03-26 19:40:21.089133 +0800 CST m=+6.004003279

    timer3 := <-ch
    fmt.Println(timer3) //2020-03-26 19:40:24.091121 +0800 CST m=+9.005942476

}

select語(yǔ)句

package main

import (
    "fmt"
    "time"
)

//22
func main() {
    /*
    分支語(yǔ)句:if、switch、select
    select類似于switch語(yǔ)句
        但是select語(yǔ)句會(huì)隨機(jī)執(zhí)行一個(gè)可運(yùn)行的case
        如果沒(méi)有case可以執(zhí)行,要看是否有default,如果有就執(zhí)行default,否則就進(jìn)入阻塞,直到有case可以運(yùn)行


     */

    ch1 := make(chan int)
    ch2 := make(chan int)

    go func() {
        time.Sleep(3 * time.Second)
        ch1 <- 100
    }()

    go func() {
        time.Sleep(3 * time.Second)
        ch2 <- 200
    }()

    select {
    case num1 := <- ch1:
        fmt.Println("ch1中獲得數(shù)據(jù)是:", num1)
    case num2,ok := <-ch2:
        if ok{
            fmt.Println("ch2中獲得的數(shù)據(jù)是:",num2)
        }else {
            fmt.Println("ch2通道已關(guān)閉")
        }
    default:
        fmt.Println("default語(yǔ)句。。。")

    }

    fmt.Println("main over...")

}

CSP并發(fā)模型

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容