Golang Day5


Channel

  • 可當不同 goroutine 的溝通管道
  • 可當 buffer queue 


簡單 Channel


package main

import(
  "fmt"
)

var Message chan string

func Bot(){
  msg := <- Message
  fmt.Println(msg)
}

func main(){
   Message =make(chan string)
   go Bot()
   Message <- "Hollo World"
   
}


Deadlock

  • 當 Channel 沒有宣告 buffer 時,若 Sneder 端送出訊息,而此時 Reciver  還未收到,Sender 端會送不出第二則訊息,此時 Sender 會 block 住造成 Dealock

package main

import(
  "fmt"
)

var Message chan string

func Bot(){
  msg := <- Message
  fmt.Println(msg)
}

func main(){
   Message =make(chan string)
   go Bot()
   Message <- "Hollo World"
   fmt.Println("first message finish")
   Message <- "This is dangerous"
   fmt.Println("second message finish")
}


如何避免 Deadlock

  • 讓接收端不斷接收訊息,避免 main thread 卡死
  • 宣告 Channel buffer

不斷接收訊息的方式

package main

import(
  "fmt"
  "time"
)

var Message chan string

func Bot(){
  for msg:= range Message{
    fmt.Println(msg)
  }
}

func main(){
   Message =make(chan string)
   go Bot()
   Message <- "Hollo World"
   fmt.Println("first message finish")
   Message <- "This is dangerous"
   fmt.Println("second message finish")

   time.Sleep(1 * time.Second) // 加入 Sleep 避免 Main thread 太快結束,看不到後面訊息
}

宣告 Channel Buffer

package main

import(
  "fmt"
  "time"
)

var Message chan string

func Bot(){
  msg := <- Message
  fmt.Println(msg)
}

func main(){
   Message =make(chan string,5) //宣告 5 個 channel buffer,可以 queue 5 個 string
   go Bot()
   Message <- "Hollo World"
   fmt.Println("first message finish")
   Message <- "This is dangerous"
   fmt.Println("second message finish")

  
}


Select

當有多個 Channel 要在同一線程控管輸出時可以使用,而決定誰輸出則是由 Golang 背後的演算法決定的;這概念相當於 C# 把 thread 丟進 thread pool 一樣是由系統控制的

package main

import(
  "fmt"
)

var Sender1Channel chan string
var Sender2Channel chan string

func Sender1(){
 Sender1Channel <- "this is channel one"
}

func Sender2(){
  Sender2Channel <- "this is channel two"
}

func main(){
   Sender1Channel =make(chan string)
   Sender2Channel =make(chan string)
   go Sender1()
   go Sender2()
   i:=0
   for{
   select{
   case msg:=<-Sender1Channel:
      fmt.Println(msg)
   case msg:=<-Sender2Channel:
      fmt.Println(msg) 
   }
   i+=1
   if i>=2{
       break
     }
   }
}

  • Share:

You Might Also Like

0 意見