如果说Goroutine是一种支持并发编程的方式,那么通道就是一种与Goroutine通信的方式。通道让数据能够进入和离开Goroutine,可方便Goroutine之间进行通信。
在其他编程语言中,并发编程通常是通过在多个进程或线程之间共享内存实现的。共享内存能够让程序同步,确保程序以合乎逻辑的方式执行。在程序执行的过程中,进程或线程可能对共享内存加锁,以禁止其他进程或线程修改它。
虽然使用共享内存有其用武之地,但Go语言使用通道在Goroutine之间收发消息,避免了使用共享内存。
c := make(chan string) 使用内置函数make创建一个通道,这是使用关键字chan指定的。 关键字chan后面的string指出这个通道将用于存储字符串数据,这意味着这个通道只能用于收发字符串值。
向通道发送信息的语法: c <- "Hello world" 这里<-表示将右边的字符串发送给左边的通道。如果通道被指定为手法字符串,则只能向它发送字符串信息,如果向它发送其他类型的信息将导致错误。
从通道那里接受消息语法如下: msg := <- c
package main import ( "fmt" "time" ) var c chan string = make(chan string) func slowFunc() { time.Sleep(time.Second * 2) c <- "slowFunc() finished" } func main() { go slowFunc() msg := <-c fmt.Println(msg) }通常,通道收到消息后就可将其发送给接收者,但有时候可能没有接收者。在这种情况下,可使用缓冲通道。缓冲意味着可将数据存储在通道中,等接收者准备就绪再交给它。要创建缓冲通道,可向内置函数make传递另一个缓冲区长度的参数。 message := make(chan string, 2)
package main import ( "fmt" "time" ) func flowFunc(c chan string) { for msg := range c { fmt.Println(msg) } } func main() { message := make(chan string, 2) message <- "hello" message <- "world" close(message) go flowFunc(message) fmt.Println("Pushed two messages onto Channel with no receivers") time.Sleep(time.Second * 1) fmt.Println("666") } // 输出 Pushed two messages onto Channel with no receivers hello world 666Goroutine是Go语言的提供的一种并发编程的方式。速度缓慢的网络调用或函数会阻塞程序的执行,而Goroutine能够让你对此进行管理。在并发编程中,通常应该避免阻塞式操作,但有时需要让代码处于阻塞状态。例如,需要在后台运行的程序必须阻塞,这样才不会退出。
Goroutine会立即返回,因此要让进程处于阻塞状态,必须采用一些流程控制技巧。例如,从通道接收并打印的消息的程序需要阻塞,以免终止。
package main import ( "fmt" "time" ) func slowFunc(c chan string) { t := time.NewTicker(1 * time.Second) for { c <- "ping" <-t.C } } func main() { message := make(chan string) go slowFunc(message) msg := <-message fmt.Println(msg) }可通过在上面程序中添加一条for语句,可不断从通道那里接收消息并将其打印到控制台。
package main import ( "fmt" "time" ) func slowFunc(c chan string) { t := time.NewTicker(1 * time.Second) for { c <- "ping" <-t.C } } func main() { message := make(chan string) go slowFunc(message) for { // 添加for msg := <-message fmt.Println(msg) } }上面将通道作为作为参数传递给函数,并在函数中向通道发送消息。要进一步指定在函数中如何使用传入的通道,可在传递通道时将其指定为只读、只写或读写的。
func channelReader(message <-chan string) { // <-位于左边表示在函数内是只读的 msg := <-message fmt.Println(msg) } func channelReaderAndWriter(message chan string) { // 无<- 可读可写 msg := <-message // 读 fmt.Println(msg) message <- "hello world" // 写 } func channelWriter(message chan<- string) { // <-位于右边表示在函数内是只写的 message <- "hello world" }