github.com/haraldrudell/parl@v0.4.176/pruntime/errors.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package pruntime
     7  
     8  import (
     9  	"errors"
    10  	"runtime"
    11  )
    12  
    13  const (
    14  	// this error string appears as multiple string literals in channel.go
    15  	rtSendOnClosedChannel  = "send on closed channel"
    16  	rtCloseOfClosedChannel = "close of closed channel"
    17  )
    18  
    19  // IsSendOnClosedChannel returns true if err’s error chain contains the
    20  // runtime error “send on closed channel”
    21  //   - runtime.plainError is an unexported named type of underlying type string
    22  //   - each error occurrence has a unique runtime.plainError value
    23  //   - runtime.plainError type have empty method RuntimeError()
    24  //   - the [runtime.Error] interface has the RuntimeError method
    25  //   - the Error method of runtime.Error returns the string value
    26  func IsSendOnClosedChannel(err error) (is bool) {
    27  
    28  	// runtimeError is any runtime.Error implementation in the err error chain
    29  	var runtimeError = IsRuntimeError(err)
    30  	if runtimeError == nil {
    31  		return // not a [runtime.Error] or runtime.plainErrror return
    32  	}
    33  
    34  	// is it the right runtime error?
    35  	return runtimeError.Error() == rtSendOnClosedChannel
    36  }
    37  
    38  // IsCloseOfClosedChannel returns true if err’s error chain contains the
    39  // runtime error “close of closed channel”
    40  func IsCloseOfClosedChannel(err error) (is bool) {
    41  
    42  	// runtimeError is any runtime.Error implementation in the err error chain
    43  	var runtimeError = IsRuntimeError(err)
    44  	if runtimeError == nil {
    45  		return // not a [runtime.Error] or runtime.plainErrror return
    46  	}
    47  
    48  	// is it the right runtime error?
    49  	return runtimeError.Error() == rtCloseOfClosedChannel
    50  }
    51  
    52  // IsRuntimeError determines if err’s error chain contains a runtime.Error
    53  //   - err1 is then a non-nil error value
    54  //   - runtime.Error is an interface describing the unexported runtime.plainError type
    55  func IsRuntimeError(err error) (err1 runtime.Error) {
    56  	// errors.As cannot handle nil
    57  	if err == nil {
    58  		return // not an error
    59  	}
    60  
    61  	// is it a runtime error?
    62  	// Go1.18: err value is a private custom type string
    63  	// the value is effectively inaccessible
    64  	// runtime defines an interface runtime.Error for its errors
    65  	errors.As(err, &err1) // updates err1 if the first error in err’s chain is a runtime Error
    66  	return
    67  }