<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                Golang 引用類型 channel 是 CSP 模式的具體實現,用于多個 goroutine 通訊。其內部實現了同步,確保并發安全。 channel概念 ~~~ a. 類似unix中管道(pipe) b. 先進先出 c. 線程安全,多個goroutine同時訪問,不需要加鎖 d. channel是有類型的,一個整數的channel只能存放整數 ~~~ channel聲明 var 變量名 chan 類型 ~~~ package main var ch0 chan int var ch1 chan string var ch2 chan map[string]string type stu struct{} var ch3 chan stu var ch4 chan *stu func main() { } ~~~ channel初始化 使用make進行初始化,比如: ~~~ package main import ( "fmt" ) var ch0 chan int = make(chan int) var ch1 chan int = make(chan int, 10) func main() { var ch2 chan string ch2 = make(chan string) var ch3 chan string ch3 = make(chan string, 1) ch4 := make(chan float32) ch5 := make(chan float64, 2) fmt.Printf("無緩沖 全局變量 chan ch0 : %v\n", ch0) fmt.Printf("有緩沖 全局變量 chan ch1 : %v\n", ch1) fmt.Printf("無緩沖 局部變量 chan ch2 : %v\n", ch2) fmt.Printf("有緩沖 局部變量 chan ch3 : %v\n", ch3) fmt.Printf("無緩沖 局部變量 chan ch4 : %v\n", ch4) fmt.Printf("有緩沖 局部變量 chan ch5 : %v\n", ch5) } ~~~ 輸出結果: ~~~ 無緩沖 全局變量 chan ch0 : 0xc420070060 有緩沖 全局變量 chan ch1 : 0xc42001c0b0 無緩沖 局部變量 chan ch2 : 0xc4200700c0 有緩沖 局部變量 chan ch3 : 0xc420054060 無緩沖 局部變量 chan ch4 : 0xc420070120 有緩沖 局部變量 chan ch5 : 0xc420050070 ~~~ 無緩沖的與有緩沖channel有著重大差別,那就是一個是同步的 一個是非同步的。 比如 c1:=make(chan int) 無緩沖 c2:=make(chan int,1) 有緩沖 c1<-1 無緩沖: 不僅僅是向 c1 通道放 1,而是一直要等有別的攜程 <-c1 接手了這個參數,那么c1<-1才會繼續下去,要不然就一直阻塞著。 有緩沖: c2<-1 則不會阻塞,因為緩沖大小是1(其實是緩沖大小為0),只有當放第二個值的時候,第一個還沒被人拿走,這時候才會阻塞。 緩沖區是內部屬性,并非類型構成要素。 ~~~ var a, b chan int = make(chan int), make(chan int, 3) ~~~ channel基本操作 不同類型channel寫入、讀取 ~~~ package main import ( "fmt" ) type Stu struct { name string } func main() { //int類型 var intChan chan int intChan = make(chan int, 10) intChan <- 10 a := <-intChan fmt.Printf("int 類型 chan : %v\n", a) //map類型 var mapChan chan map[string]string mapChan = make(chan map[string]string, 10) m := make(map[string]string, 16) m["stu01"] = "001" m["stu02"] = "002" m["stu03"] = "003" mapChan <- m b := <-mapChan fmt.Printf("map 類型 chan : %v\n", b) //結構體 var stuChan chan Stu stuChan = make(chan Stu, 10) stu := Stu{ name: "Murphy", } stuChan <- stu tempStu := <-stuChan fmt.Printf("struct 類型 chan : %v\n", tempStu) //結構體內存地址值 var stuChanId chan *Stu stuChanId = make(chan *Stu, 10) stuId := &Stu{ name: "Murphy", } stuChanId <- stuId tempStuId := <-stuChanId fmt.Printf("*struct 類型 chan : %v\n", tempStuId) fmt.Printf("*struct 類型 chan 取值 : %v\n", *(tempStuId)) //接口 var StuInterChain chan interface{} StuInterChain = make(chan interface{}, 10) stuInit := Stu{ name: "Murphy", } //存 StuInterChain <- &stuInit //取 mFetchStu := <-StuInterChain fmt.Printf("interface 類型 chan : %v\n", mFetchStu) //轉 var mStuConvert *Stu mStuConvert, ok := mFetchStu.(*Stu) if !ok { fmt.Println("cannot convert") return } fmt.Printf("interface chan轉 *struct chan : %v\n", mStuConvert) fmt.Printf("interface chan轉 *struct chan 取值 : %v\n", *(mStuConvert)) } ~~~ 輸出結果: ~~~ int 類型 chan : 10 map 類型 chan : map[stu02:002 stu03:003 stu01:001] struct 類型 chan : {Murphy} *struct 類型 chan : &{Murphy} *struct 類型 chan 取值 : {Murphy} interface 類型 chan : &{Murphy} interface chan轉 *struct chan : &{Murphy} interface chan轉 *struct chan 取值 : {Murphy} ~~~ channel 寫入、讀取、遍歷、關閉: ~~~ package main import ( "fmt" ) func main() { ch := make(chan int, 11) //寫入chan ch <- 99 for i := 0; i < 10; i++ { ch <- i } fmt.Printf("writed chan ch : %v\n", ch) //讀取chan first_chan, ok := <-ch if ok { fmt.Printf("first chan is %v\n", first_chan) } ch <- 10 //遍歷chan for value := range ch { fmt.Println(value) if value == 10 { // 關閉chan close(ch) //break // 在這里break循環也可以 } } fmt.Println("after range or close ch!") } ~~~ 輸出結果: ~~~ first chan is 99 0 1 2 3 4 5 6 7 8 9 10 after range or close ch! ~~~ channel關閉 channel關閉后,就不能取出數據了 1. 使用內置函數close進行關閉,chan關閉之后,for range遍歷chan中已經存在的元素后結束 2. 使用內置函數close進行關閉,chan關閉之后,沒有使用for range的寫法需要使用,v, ok := <- ch進行判斷chan是否關閉 ~~~ package main import "fmt" func main() { var ch chan int ch = make(chan int, 5) for i := 0; i < 5; i++ { ch <- i } close(ch) for { var b int b, ok := <-ch if ok == false { fmt.Println("chan is close") break } fmt.Println(b) } } ~~~ 輸出結果: ~~~ 0 1 2 3 4 chan is close ~~~ 如果將close(ch)注釋掉,意思是不關閉管道,那么會出現dead lock死鎖 因為存入管道5個數字,然后無限取數據,會出現死鎖。 ~~~ package main import "fmt" func main() { var ch chan int ch = make(chan int, 5) for i := 0; i < 5; i++ { ch <- i } // close(ch) for { var b int b, ok := <-ch if ok == false { fmt.Println("chan is close") break } fmt.Println(b) } } ~~~ 輸出結果: ~~~ 0 1 2 3 4 fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan receive]: main.main() /Users/***/Desktop/go/src/main.go:16 +0xfb exit status 2 ~~~ range 遍歷 chan ~~~ package main import "fmt" func main() { var ch chan int ch = make(chan int, 10) for i := 0; i < 10; i++ { ch <- i } close(ch) for v := range ch { fmt.Println(v) } } ~~~ 輸出結果: ~~~ 0 1 2 3 4 5 6 7 8 9 ~~~ 同樣如果將close(ch)注釋掉,意思是不關閉管道,那么會出現dead lock死鎖 因為存入管道10個數字,然后無限取數據,在取出來第10個數據,在次range管道,會dead lock。 ~~~ package main import "fmt" func main() { var ch chan int ch = make(chan int, 10) for i := 0; i < 10; i++ { ch <- i } // close(ch) for v := range ch { fmt.Println(v) } } ~~~ 輸出結果: ~~~ 0 1 2 3 4 5 6 7 8 9 fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan receive]: main.main() /Users/***/Desktop/go/src/main.go:14 +0x106 exit status 2 ~~~ 除用 range 外,還可用 ok-idiom 模式判斷 channel 是否關閉。 ~~~ package main import "fmt" func main() { var ch chan int ch = make(chan int, 10) for i := 0; i < 10; i++ { ch <- i } close(ch) for { if d, ok := <-ch; ok { fmt.Println(d) } else { break } } } ~~~ 輸出結果: ~~~ 0 1 2 3 4 5 6 7 8 9 ~~~ 向 closed channel 發送數據引發 panic 錯誤,接收立即返回零值。而 nil channel, 無論收發都會被阻塞。 ~~~ package main func main() { ch := make(chan int, 1) close(ch) ch <- 2 } ~~~ 輸出結果: ~~~ panic: send on closed channel goroutine 1 [running]: main.main() /Users/***/Desktop/go/src/main.go:6 +0x63 exit status 2 ~~~ 內置函數 len 返回未被讀取的緩沖元素數量,cap 返回緩沖區大小。 ~~~ package main import "fmt" func main() { ch1 := make(chan int) ch2 := make(chan int, 3) ch2 <- 1 fmt.Println(len(ch1), cap(ch1)) fmt.Println(len(ch2), cap(ch2)) } ~~~ 輸出結果: ~~~ 0 0 1 3 ~~~ 對chan進行select操作 select 語句類似于 switch 語句,但是select會隨機執行一個可運行的case。如果沒有case可運行,它將阻塞,直到有case可運行。 ~~~ package main import ( "fmt" ) func main() { ch1 := make(chan int, 1) ch1 <- 1 ch2 := make(chan int, 1) ch2 <- 2 select { case k1 := <-ch1: fmt.Println(k1) case k2 := <-ch2: fmt.Println(k2) default: fmt.Println("chan") } } ~~~ 輸出結果: ~~~ //結果1,2隨機 ~~~ chan的只讀和只寫 a. 只讀chan的聲明 var 變量名 <-chan 類型 ~~~ package main var ch0 <-chan int var ch1 <-chan string var ch2 <-chan map[string]string type stu struct{} var ch3 <-chan stu var ch4 <-chan *stu func main() { } ~~~ b. 只寫chan的聲明 var 變量名 chan<- 類型 ~~~ package main var ch0 chan<- int var ch1 chan<- string var ch2 chan<- map[string]string type stu struct{} var ch3 chan<- stu var ch4 chan<- *stu func main() { } ~~~ channel單向 :可以將 channel 隱式轉換為單向隊列,只收或只發。 ~~~ package main import ( "fmt" ) func main() { c := make(chan int, 3) var send chan<- int = c // send-only var recv <-chan int = c // receive-only send <- 1 // <-send // Error: receive from send-only type chan<- int val, ok := <-recv if ok { fmt.Println(val) } // recv <- 2 // Error: send to receive-only type <-chan int } ~~~ 輸出結果: ~~~ 1 ~~~ 不能將單向 channel 轉換為普通 channel。 ~~~ package main func main() { c := make(chan int, 3) var send chan<- int = c // send-only var recv <-chan int = c // receive-only ch1 := (chan int)(send) // Error: cannot convert type chan<- int to type chan int ch2 := (chan int)(recv) // Error: cannot convert type <-chan int to type chan int } ~~~ 輸出結果: ~~~ ./main.go:8:19: cannot convert send (type chan<- int) to type chan int ./main.go:9:19: cannot convert recv (type <-chan int) to type chan int ~~~ channel 是第一類對象,可傳參 (內部實現為指針) 或者作為結構成員。 ~~~ package main import "fmt" type Request struct { data []int ret chan int } func NewRequest(data ...int) *Request { return &Request{data, make(chan int, 1)} } func Process(req *Request) { x := 0 for _, i := range req.data { x += i } req.ret <- x } func main() { req := NewRequest(10, 20, 30) Process(req) fmt.Println(<-req.ret) } ~~~ 輸出結果: ~~~ 60 ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看