github.com/haraldrudell/parl@v0.4.176/internal/cyclebreaker/err-ch-wait.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package cyclebreaker 7 8 import "github.com/haraldrudell/parl/perrors" 9 10 // ErrChWait is a deferrable function receiving an error value on a channel 11 // - used to wait for a goroutine 12 // 13 // Usage: 14 // 15 // var err error 16 // defer errorHandler(&err) 17 // 18 // var errCh = make(chan error, 1) 19 // go someFunc(errCh) 20 // defer parl.ErrChWait(errCh, &err) 21 // 22 // func someFunc(errCh chan<- error) { 23 // var err error 24 // defer parl.SendErr(errCh, &err) 25 // defer parl.PanicToErr(errp) 26 func ErrChWait(errCh <-chan error, errp *error) { 27 if errp == nil { 28 panic(perrors.NewPF("errp cannot be nil")) 29 } else if errCh == nil { 30 panic(perrors.NewPF("errCh cannot be nil")) 31 } 32 // blocks here 33 if err := <-errCh; err != nil { 34 *errp = perrors.AppendError(*errp, err) 35 } 36 } 37 38 // SendErr sends error as the final action of a goroutine 39 // - SendErr should only panic from structural coding problems 40 func SendErr(errCh chan<- error, errp *error) { 41 if errp == nil { 42 panic(perrors.NewPF("errp cannot be nil")) 43 } 44 didSend, isNilChannel, isClosedChannel, err := ChannelSend(errCh, *errp, SendNonBlocking) 45 if didSend { 46 return // error value sent return 47 } else if isNilChannel { 48 err = perrors.ErrorfPF("fatal: error channel nil: %w", err) 49 } else if isClosedChannel { 50 err = perrors.ErrorfPF("fatal: error channel closed: %w", err) 51 } else if err != nil { 52 err = perrors.ErrorfPF("fatal: panic when sending on error channel: %w", err) 53 } else { 54 err = perrors.NewPF("fatal: error channel blocking on send") 55 } 56 panic(err) 57 }