1package chans 2 3import "runtime" 4 5// Ranger returns a Sender and a Receiver. The Receiver provides a 6// Next method to retrieve values. The Sender provides a Send method 7// to send values and a Close method to stop sending values. The Next 8// method indicates when the Sender has been closed, and the Send 9// method indicates when the Receiver has been freed. 10// 11// This is a convenient way to exit a goroutine sending values when 12// the receiver stops reading them. 13func Ranger[T any]() (*Sender[T], *Receiver[T]) { 14 c := make(chan T) 15 d := make(chan bool) 16 s := &Sender[T]{values: c, done: d} 17 r := &Receiver[T]{values: c, done: d} 18 runtime.SetFinalizer(r, r.finalize) 19 return s, r 20} 21 22// A sender is used to send values to a Receiver. 23type Sender[T any] struct { 24 values chan<- T 25 done <-chan bool 26} 27 28// Send sends a value to the receiver. It returns whether any more 29// values may be sent; if it returns false the value was not sent. 30func (s *Sender[T]) Send(v T) bool { 31 select { 32 case s.values <- v: 33 return true 34 case <-s.done: 35 return false 36 } 37} 38 39// Close tells the receiver that no more values will arrive. 40// After Close is called, the Sender may no longer be used. 41func (s *Sender[T]) Close() { 42 close(s.values) 43} 44 45// A Receiver receives values from a Sender. 46type Receiver[T any] struct { 47 values <-chan T 48 done chan<- bool 49} 50 51// Next returns the next value from the channel. The bool result 52// indicates whether the value is valid, or whether the Sender has 53// been closed and no more values will be received. 54func (r *Receiver[T]) Next() (T, bool) { 55 v, ok := <-r.values 56 return v, ok 57} 58 59// finalize is a finalizer for the receiver. 60func (r *Receiver[T]) finalize() { 61 close(r.done) 62} 63