golang channel

ex1

package main
/*
goroutine 是由GO運行時管理的輕量級線程
go f(x,y, z) 就啓動了一個goroutine, 其中f,x,y,z在當前goroutine中當即計算, f內容的執行在另外一個新goroutine中。
全部的goroutine都是運行在同一個地址空間中, 全部訪問共享內存時,必須進行同步處理。
在sync包中上, 提供了同步須要的原語
*/
import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")
}

ex2

package main


/*
Channels 就管道,就是劇導管, 你可能管道操做符進行讀寫, 操做符爲 <-
ch <- v    // 把 v 寫入管道
v := <-ch  // 從 ch 管道中讀出到 v 變量中
數據的流向, 就箭頭的指向。
全部 maps , slices, channels 複雜結構都須要經過make來建立
ch := make (chan int)
默認狀況下, 發收都須要對端準備好了才行, 這樣的前提使得goroutine同步就不須要顯式的鎖處理,下降了複雜度,簡化的設計。

下面示例代碼, 對slice的值求和。 分佈式的工做在兩個goroutine中。當其兩個完成計算時,最終結果也計算出來了
*/

import "fmt"

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)
    x, y := <-c, <-c // receive from c

    fmt.Println(x, y, x+y)
}

ex3

/*
Channels 就管道
導管經過第二個參數,是能夠指定其緩存長度的
ch := make(chan int, 100)
當管道滿時, 發送會阻塞
當管道空時, 接收會阻塞

修改下面的代碼,能夠進行測試一下
*/

package main

import (
    "fmt"
    "time"
)

// 例一、寫阻塞等待
func put_chan(ch chan int, n int)  {
    for i := 0 ; i < n;  i++{
        fmt.Println("put: ", i, time.Now().UTC())
        ch <- i
    }
    close(ch)
}

func read_chan(ch chan int, quit chan int)  {
    for c := range ch{
        time.Sleep(time.Duration(time.Second * 3))
        fmt.Println(c, time.Now().UTC())
    }
    time.Sleep(time.Duration(time.Second * 3))
    quit <- 1
}
func main() {
    ch := make(chan int, 2)
    quit := make(chan int)
    go put_chan(ch, 10)
    go read_chan(ch, quit)


    fmt.Println("end", <- quit, time.Now().UTC())

}

//// 例二、讀阻塞等待
//func put_chan(ch chan int, n int)  {
//  for i := 0 ; i < n;  i++{
//      time.Sleep(time.Duration(time.Second * 3))
//      ch <- i
//  }
//  time.Sleep(time.Duration(time.Second * 3))
//  close(ch)
//}
//
//func read_chan(ch chan int, quit chan int)  {
//  for c := range ch{
//      fmt.Println(c, time.Now())
//  }
//  quit <- 1
//}
//func main() {
//  ch := make(chan int, 2)
//  quit := make(chan int)
//  go put_chan(ch, 2)
//  go read_chan(ch, quit)
//
//
//  fmt.Println("end", <- quit, time.Now())
//
//}

// 例三、測試中發現,系統檢測會出現死鎖
//func main() {
//  ch := make(chan int, 2)
//  ch <- 1
//  ch <- 2
//  fmt.Println(<-ch)
//  fmt.Println(<-ch)
//  fmt.Println(<-ch)
//  fmt.Println("end")
//
//}

ex4

/*
Channels Range & Close 範圍排列與關閉
發送者能夠經過關閉通道來通知沒有更多數據須要發送了。
接收者能夠檢測通道是否已經關閉了,經過指定第二個參數來實現,具體以下
v , ok := <- ch
當ok爲false, 則通道已經關閉,沒有數據了。
或者可使用循環 for i := range c 來取數據,至到通道關閉。
注意<慣例>:
   1. 應該只讓發送者來關閉通道。 絕對不要讓接收者來關閉。 在一個已經關閉了的通道上發數據會引起panic
   2. 通道,只在最終不要了, 須要終止的時候纔來關閉之
*/

package main

import (
    "fmt"
)

func fibonacci(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
}

func main() {
    c := make(chan int, 10)
    go fibonacci(cap(c), c)
    for i := range c {
        fmt.Println(i)
    }
}

ex5

/*
Channels  select  選擇查詢操做
選擇查詢語句, 讓當前goroutine 等待多個通信操做
當沒有條件知足時, select阻塞
當有  條件知足時, select執行
當有多條件知足時, select隨機執行知足條件之一
*/

package main

import "fmt"

func fibonacci(c, quit chan int) {
    x, y := 0, 1
    for {
        select {
        case c <- x:    // 寫
            x, y = y, x+y
        case <-quit:    // 讀
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}

ex6

/*
Channels  select  選擇查詢操做
缺省選擇, 當沒有case條件知足時, 直接選擇默認條件
*/

package main

import (
    "fmt"
    "time"
)

func main() {
    tick := time.Tick(100 * time.Millisecond)
    boom := time.After(500 * time.Millisecond)
    for {
        select {
        case <-tick:
            fmt.Println("tick.")
        case <-boom:
            fmt.Println("BOOM!")
            return
        default:
            fmt.Println("    .")
            time.Sleep(50 * time.Millisecond)
        }
    }
}
相關文章
相關標籤/搜索