You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
1.3 KiB
Go
92 lines
1.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"time"
|
|
)
|
|
|
|
func trySend[T any](c chan<- T, v T) bool {
|
|
select {
|
|
case c <- v:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func raceSame[T any](cs ...<-chan T) T {
|
|
done := make(chan T)
|
|
defer close(done)
|
|
|
|
for _, c := range cs {
|
|
go func(c <-chan T) {
|
|
trySend(done, <-c)
|
|
}(c)
|
|
}
|
|
|
|
return <-done
|
|
}
|
|
|
|
type Awaiter interface {
|
|
Await()
|
|
}
|
|
|
|
type awaiterChan[T any] <-chan T
|
|
|
|
func (rc awaiterChan[T]) Await() { <-rc }
|
|
|
|
type targetChan[T any] struct {
|
|
c <-chan T
|
|
target *T
|
|
}
|
|
|
|
func (rc targetChan[T]) Await() { *rc.target = <-rc.c }
|
|
|
|
func raceAny(rs ...Awaiter) {
|
|
done := make(chan struct{})
|
|
defer close(done)
|
|
|
|
for _, r := range rs {
|
|
go func(r Awaiter) {
|
|
r.Await()
|
|
trySend(done, struct{}{})
|
|
}(r)
|
|
}
|
|
|
|
<-done
|
|
}
|
|
|
|
func main() {
|
|
c1 := make(chan string)
|
|
c2 := make(chan int)
|
|
c3 := make(chan float64)
|
|
|
|
go func() {
|
|
defer close(c1)
|
|
time.Sleep(300 * time.Millisecond)
|
|
c1 <- "1"
|
|
}()
|
|
go func() {
|
|
defer close(c2)
|
|
time.Sleep(400 * time.Millisecond)
|
|
c2 <- 2
|
|
}()
|
|
go func() {
|
|
defer close(c3)
|
|
time.Sleep(200 * time.Millisecond)
|
|
c3 <- 3.0
|
|
}()
|
|
|
|
var result2 int
|
|
var result3 float64
|
|
|
|
raceAny(
|
|
awaiterChan[string](c1),
|
|
targetChan[int]{c2, &result2},
|
|
targetChan[float64]{c3, &result3},
|
|
)
|
|
|
|
fmt.Println(result2, result3)
|
|
}
|