1 package chans 2 3 import "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. 13 func 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. 23 type 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. 30 func (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. 41 func (s *Sender[T]) Close() { 42 close(s.values) 43 } 44 45 // A Receiver receives values from a Sender. 46 type 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. 54 func (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. 60 func (r *Receiver[T]) finalize() { 61 close(r.done) 62 } 63