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

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)
}