chan - skynocover/Wiki-for-GoLang GitHub Wiki
宣告
chan T //可以用來發送與接收的通道
chan<-T //只能用來發送
<-chan T // 只能用來接收
初始化
ci := make(chan int) //整数無緩衝
cj := make(chan int, 0) //整数無緩衝
cp := make(chan *os.File, 100) //指向文件指標有緩衝
緩衝表channel可以容納元素的大小
數據發送
c := make(chan int) //建立通道
defer close(c)
go func() { c <- 3 + 4 }() //計算3+4
i := <-c //等到接收到7之後才動作
fmt.Println(i)
可以用ok確認是否有收到
x, ok := <-ch
x, ok = <-ch
var x, ok = <-ch
close
若channel被關閉還繼續發送會出現panic
func main() {
go func() {
time.Sleep(time.Hour)
}()
c := make(chan int, 10)
c <- 1
c <- 2
close(c)
c <- 3
}
但是可以繼續讀取
c := make(chan int, 10)
c <- 1
c <- 2
close(c)
fmt.Println(<-c) //1
fmt.Println(<-c) //2
fmt.Println(<-c) //0
fmt.Println(<-c) //0
使用range則會在關閉後跳出
c := make(chan int, 10)
c <- 1
c <- 2
close(c)
for i := range c {
fmt.Println(i)
}
range處理
for range
func main() {
go func() {
time.Sleep(1 * time.Hour)
}()
c := make(chan int)
go func() {
for i := 0; i < 10; i = i + 1 {
c <- i
}
close(c)
}()
for i := range c {
fmt.Println(i)
}
fmt.Println("Finished")
}
若沒有將c關掉則會一直卡在 for range那一行
使用select
select類似switch 但是只用在chan
參照條目select
使用timer和ticker兩個channel
timer表定時器
下面那個會等待兩秒後才執行
timer1 := time.NewTimer(time.Second * 2)
<-timer1.C
fmt.Println("Timer 1 expired")
也可以用timestop來停止計時
timer2 := time.NewTimer(time.Second)
go func() {
<-timer2.C
fmt.Println("Timer 2 expired")
}()
stop2 := timer2.Stop()
if stop2 {
fmt.Println("Timer 2 stopped")
}
ticker表定時觸發的計時器
下面例子表每500號秒觸發一次
ticker := time.NewTicker(time.Millisecond * 500)
go func() {
for t := range ticker.C {
fmt.Println("Tick at", t)
}
}()
通知任務完成
func worker(done chan bool) {
time.Sleep(time.Second)
// 通知任务已完成
done <- true
}
func main() {
done := make(chan bool, 1)
go worker(done)
// 等待任务完成
<-done
}