Go
Выбор и каналы
Поиск…
Вступление
select
обеспечивает простой способ работы с каналами и выполнения более сложных задач. Он часто используется для ряда целей: - обработка тайм-аутов. - Когда есть несколько каналов для чтения, выбор будет произвольно считываться с одного канала с данными. - Предоставление простого способа определить, что произойдет, если на канале нет данных.
Синтаксис
- Выбрать {}
- выберите {case true:}
- select {case incomingData: = <-someChannel:}
- выберите {default:}
Простой выбор работы с каналами
В этом примере мы создаем goroutine (функция, работающая в отдельном потоке), которая принимает параметр chan
, и просто петли, каждый раз отправляя информацию в канал.
В main
у нас есть цикл for
и select
. select
блокирует обработку до тех пор, пока один из операторов case
станет истинным. Здесь мы объявили два случая; во-первых, когда информация поступает через канал, а другая - в случае отсутствия другого случая, который известен как default
.
// Use of the select statement with channels (no timeouts)
package main
import (
"fmt"
"time"
)
// Function that is "chatty"
// Takes a single parameter a channel to send messages down
func chatter(chatChannel chan<- string) {
// Clean up our channel when we are done.
// The channel writer should always be the one to close a channel.
defer close(chatChannel)
// loop five times and die
for i := 1; i <= 5; i++ {
time.Sleep(2 * time.Second) // sleep for 2 seconds
chatChannel <- fmt.Sprintf("This is pass number %d of chatter", i)
}
}
// Our main function
func main() {
// Create the channel
chatChannel := make(chan string, 1)
// start a go routine with chatter (separate, non blocking)
go chatter(chatChannel)
// This for loop keeps things going while the chatter is sleeping
for {
// select statement will block this thread until one of the two conditions below is met
// because we have a default, we will hit default any time the chatter isn't chatting
select {
// anytime the chatter chats, we'll catch it and output it
case spam, ok := <-chatChannel:
// Print the string from the channel, unless the channel is closed
// and we're out of data, in which case exit.
if ok {
fmt.Println(spam)
} else {
fmt.Println("Channel closed, exiting!")
return
}
default:
// print a line, then sleep for 1 second.
fmt.Println("Nothing happened this second.")
time.Sleep(1 * time.Second)
}
}
}
Попробуйте на игровой площадке Go!
Использование select с тайм-аутами
Итак, здесь я удалил циклы for
и сделал тайм-аут , добавив второй case
в select
который возвращается через 3 секунды. Поскольку select
просто ждет, пока ЛЮБОЙ случай не будет истинным, произойдет второй case
, а затем наш скрипт закончится, и chatter()
никогда не получит шанс закончить.
// Use of the select statement with channels, for timeouts, etc.
package main
import (
"fmt"
"time"
)
// Function that is "chatty"
//Takes a single parameter a channel to send messages down
func chatter(chatChannel chan<- string) {
// loop ten times and die
time.Sleep(5 * time.Second) // sleep for 5 seconds
chatChannel<- fmt.Sprintf("This is pass number %d of chatter", 1)
}
// out main function
func main() {
// Create the channel, it will be taking only strings, no need for a buffer on this project
chatChannel := make(chan string)
// Clean up our channel when we are done
defer close(chatChannel)
// start a go routine with chatter (separate, no blocking)
go chatter(chatChannel)
// select statement will block this thread until one of the two conditions below is met
// because we have a default, we will hit default any time the chatter isn't chatting
select {
// anytime the chatter chats, we'll catch it and output it
case spam := <-chatChannel:
fmt.Println(spam)
// if the chatter takes more than 3 seconds to chat, stop waiting
case <-time.After(3 * time.Second):
fmt.Println("Ain't no time for that!")
}
}