这个例子使用 Golang 的非缓冲通道。未缓冲的通道一次只包含一个值。因此,它们被称为阻塞通道,并像这样创建:make(chan TYPE) 。为了演示使用方法,我们将每2秒一个城市的问候。然而,如果在问候中出现5秒的延迟,我们将使应用程序超时。请阅读内联评论以获得详细解释。
例子1
如果你把睡眠时间从2秒增加到5/+秒以下,应用程序将超时而不打印任何东西。在select 语句中没有一个default 块,所以它将阻塞,直到通过我们的通道收到一个消息,然后继续阻塞,或者遇到超时情况自动退出。在这种情况下,main 函数是接收者,welcome 函数是发送者。
package main
import (
"fmt"
"os"
"time"
)
func main() {
// List of cities.
cities := []string{"London", "Istanbul", "Berlin", "Madrid"}
// Create unbuffered channel.
ch := make(chan string)
// Pass channel and cities to welcome function and run it as goroutine.
go welcome(ch, cities)
// Indefinitely wait for the channel to return something.
for {
select {
// If something was received through the channel, print it.
case msg := <-ch:
fmt.Println(msg)
// If nothing was received through the channel for 5 seconds, timeout.
case <-time.After(5 * time.Second):
fmt.Println("timeout")
os.Exit(0)
}
}
}
// welcome accepts write-only channel and list of cities.
func welcome(ch chan<- string, cities []string) {
// Loop through the cities.
for _, city := range cities {
// Sleep 2 seconds before writing to the channel below.
time.Sleep(1 * time.Second)
// Write (send) greeting message to the channel.
ch <- fmt.Sprintf("Welcome to %s", city)
}
}
输出
$ go run -race cmd/client/main.go
Welcome to London
Welcome to Istanbul
Welcome to Berlin
Welcome to Madrid
timeout
例2
这是一个更简单的版本,因为我们没有使用超时。相反,我们明确地关闭通道:
package main
import (
"fmt"
"time"
)
func main() {
// List of cities.
cities := []string{"London", "Istanbul", "Berlin", "Madrid"}
// Create unbuffered channel.
ch := make(chan string)
// Pass channel and cities to welcome function and run it as goroutine.
go welcome(ch, cities)
// Indefinitely wait for the channel to return something.
for msg := range ch {
fmt.Println(msg)
}
fmt.Println("done")
}
// welcome accepts write-only channel and list of cities.
func welcome(ch chan<- string, cities []string) {
// Loop through the cities.
for _, city := range cities {
// Sleep 2 seconds before writing to the channel below.
time.Sleep(1 * time.Second)
// Write (send) greeting message to the channel.
ch <- fmt.Sprintf("Welcome to %s", city)
}
// Close the channel so that range loop knows when to exit.
close(ch)
}
Welcome to London
Welcome to Istanbul
Welcome to Berlin
Welcome to Madrid
done
例三
在这个例子中,我们是一个一个地传递城市,而不是全部:
package main
import (
"fmt"
"time"
)
func main() {
// List of cities.
cities := []string{"London", "Istanbul", "Berlin", "Madrid"}
// Create unbuffered channel.
ch := make(chan string)
for _, city := range cities {
// Pass channel and city to welcome function and run it as goroutine.
go welcome(ch, city)
// Indefinitely wait for the channel to return something.
for msg := range ch {
fmt.Println(msg)
break
}
}
fmt.Println("done")
}
// welcome accepts write-only channel and city.
func welcome(ch chan<- string, city string) {
// Sleep 2 seconds before writing to the channel below.
time.Sleep(1 * time.Second)
// Write (send) greeting message to the channel.
ch <- fmt.Sprintf("Welcome to %s", city)
}
Welcome to London
Welcome to Istanbul
Welcome to Berlin
Welcome to Madrid
done