笔记 - goroutine、channel详解
goroutine
channel通道 (goroutine通信)
package main import "fmt" func main() { var ch1 chan bool ch1 = make(chan bool) go func() { for i := 0; i < 10; i++ { fmt.Println("子goroutine:", i) } ch1 <- true fmt.Println("over") }() // 读数据是阻塞的 <-ch1 fmt.Println("main over") }
关闭通道及范围循环
package main import ( "fmt" "time" ) func main() { ch1 := make(chan int) go sendData(ch1) // 第一种方式读取通道 for { time.Sleep(1 * time.Second) v, ok := <-ch1 if !ok { fmt.Println("读完了 over") break } fmt.Println("读取数据", v) } // 第二种方式读取通道 for v := range ch1 { // v <- ch1 fmt.Println("数据:", v) } fmt.Println("main.... over...") } func sendData(ch1 chan int) { for i := 0; i < 10; i++ { time.Sleep(1 * time.Second) ch1 <- i } // 关闭通道 close(ch1) }
缓存通道(可理解为一个定长的队列)
package main import ( "fmt" "strconv" ) func main() { /** * 非缓冲 make(chan T) * 缓冲 make(chan T, capacity) * 发送: 缓冲区的数据满了,才会阻塞 * 接受: 缓冲区的数据空了,才会阻塞 */ ch1 := make(chan int) fmt.Println(len(ch1), cap(ch1)) ch1 <- 100 ch2 := make(chan int, 5) fmt.Println(len(ch2), cap(ch2)) ch2 <- 100 fmt.Println(len(ch2), cap(ch2)) ch3 := make(chan string, 4) go sendData(ch3) for { v, ok := <-ch3 if !ok { fmt.Println("读完了...", ok) break } fmt.Println("读取的数据是:", v) } fmt.Println("main over") } func sendData(ch chan string) { for i := 0; i < 10; i++ { ch <- "data" + strconv.Itoa(i) fmt.Printf("子gorountine第%d个数据", i) } close(ch) }
定向通道
package main import "fmt" func main() { /** 双向通道: chan T chan <- data, 发送数据,写出 data <- chan, 获取数据,读取 单向通道: 定向 chan <- T, 只支持写 <-chan T, 只支持读 */ ch1 := make(chan string) ch2 := make(chan<- int) // 单项,只能写,不能读 ch3 := make(<-chan int) // 单项。只能读,不能写 go sendData(ch1) data := <-ch1 // 读取 fmt.Println("子roroutine数据", data) ch1 <- "我是main" } func sendData(ch1 chan string) { ch1 <- "我是子" data := <-ch1 fmt.Println("main goroutine传来:", data) }
本作品采用《CC 协议》,转载必须注明作者和本文链接