Proposal for errors pkg. OneOf and IsOnly functions

81 views
Skip to first unread message

Gonzalo Spina

unread,
Jun 11, 2021, 4:42:02 PM6/11/21
to golang-nuts
  • Would you consider yourself a novice, intermediate, or experienced Go programmer? Experienced
  • What other languages do you have experience with? VB.Net, Python, Javascript, Rust
  • Would this change make Go easier or harder to learn, and why? None
  • Has this idea, or one like it, been proposed before? No
  • Who does this proposal help, and why? -
  • What is the proposed change? 
    • Please describe as precisely as possible the change to the language.
      While using go and the built-in fuction Is of the error package I found natural and complementary to this function the posibility to check if an error wrapped is IsOnly one out of many or to converge many errors into a single result
    • What would change in the language spec? Nothing
    • Please also describe the change informally, as in a class teaching Go.
      OneOf(err, Err1, Err2) returns true or false if the given error Is either Err1 or Err 2
  • Is this change backward compatible? Yes
  • Show example code before and after the change. 

    Before:
    // Example of OneOf
    m, err := SomeFunctionOrMethod()
    if err != nil {
       if errors.Is(err, Err1) || errors.Is(err, Err2) || errors.Is(err, Err3) {
            // do something
       }
    }

    // Example of IsOnly
    m, err := SomeFunction
    if err != nil {
       if errors.Is(err, Err1) && !errors.Is(err, Err2) && !errors.Is(err, Err3) {
            // do something
       }
    }

    After 
    // Example of OneOf
    m, err := SomeFunctionOrMethod()
    if err != nil {   
        if errors.OneOf(err, Err1,Err2, Err3) {
            // do something
        }
    }

    // Example of IsOnly
    m, err := SomeFunctionOrMethod()
    if err != nil {   
        if errors.IsOnly(err, Err1) {
            // do something
        }
    }


  • What is the cost of this proposal? (Every language change has a cost).
    • How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected? Only package error, and only new code.
    • What is the compile time cost? Doesn't apply
    • What is the run time cost? Doesn't apply
  • Can you describe a possible implementation?
    Every time you need to validate or change the behavior of a process where more than one error is possible and the possible outcomes for those errors are different. For example a REST service that returns different status codes for different business errors
  • How would the language spec change?
    Two functions would be added to the package errors
  • Orthogonality: how does this change interact or overlap with existing features?
    The 'OneOf' function may use the existing 'Is' function of the package errors
  • Is the goal of this change a performance improvement? No
  • Does this affect error handling? Technically yes
  • Is this about generics? No

// OneOf to tell if the error exists in the array
func OneOf(err error, targets ...error) bool {
    if len(targets) == 0 {
        return false
    }
    for _, target := range targets {
        if Is(err, target) {
            return true
        }
    }
    return false
}

// IsOnly tells if the error is one specific type only
func IsOnly(err, target error) bool {
    if target == nil {
        return err == target
    }
    isComparable := reflect.TypeOf(target).Comparable()
    if isComparable && err != target {
        return false
    }
    if x, ok := err.(interface{ Is(error) bool }); ok && !x.Is(target) {
        return false
    }
    if err = errors.Unwrap(err); err != nil {
        return false
    }
    return true
}
Reply all
Reply to author
Forward
0 new messages