Skip to content

proposal: Go 2: error map or log for error handling #49535

@sergeyprokhorenko

Description

@sergeyprokhorenko

New better proposal #50280 is ready

I propose the interrelated changes to the Go language:

  1. Each declared or imported function (including method) must automatically and implicitly declare and initialize an error map, as does the operator @function_name := map[string]bool{}. Alternatively the error_ or error. prefix can be used before the function name instead of the @ prefix, or the names of the function and the error map can be the same.

  2. The error map must be visible both inside the body of the function and in the scope (that is, in visibility area outside the function body) of the declared or imported function. The scope (that is, visibility area) of the error map is the same as scope (that is, visibility area) of the parameters of function.

But Apache Kafka attracts by the idea of a more flexible, dynamical and centralized management of the areas of visibility (topics) of messages (about errors). See description of the error log

  1. The content of the error map should be updated and visible instantly, well before the called function returns, so that the calling function can decide in advance whether the called function needs to be interrupted and how to handle errors.

Cases of assigning functions to variables and transferring functions to other functions etc require special research.
Instead of a map, we can use another container for error messages, if it turns out to be more convenient: set, slice, stack, etc.

Description of use:

Programmers should use error types as keys in the error map.

Each function can throw several errors of different types and severity, which can then be handled in different ways (with or without exiting the function where the error occured, with or without return of parameters). If an error occurs, then the value of its type in the error map must be true. Therefore, the operator @function_name["error_type"] = true is required in the function body, but it's preferable that warning("error_type") and escape("error_type") (with escape from erroneous function) play its role.

If the corresponding function is used several times in the same scope (that is, in visibility area), then all different types of errors will appear in the error map each time when function is used.

If, when checking the expression @function_name["error_type"] in an if or switch statement, an error type was used that is not in the error map, then value false will be returned. It is convenient and obvious. A desision table can be used together with an error map for error handling and informing in difficult cases.

Benefits of the proposal:

  1. Very concise and obvious notation even for a novice Go programmer
  2. Change is backward compatible with Go 1 (replaces, but can be used in parallel with existing error handling methods). Therefore it can be done before Go 2
  3. Simple implementation
  4. Doesn't affect compilation time and performance
  5. Explicit and composite error naming in the calling function
  6. Аrbitrary and easy error naming in the function in which the error occurred (including dynamic name generation)
  7. Ability to send errors along the chain of function calls
  8. The compiler can catch unhandled explicitly specified errors
  9. Each function can throw several errors of different types and severity, which can then be handled in different ways (including with or without instantaneous exiting the function where the error occured, with or without returning parameters)
  10. If the corresponding function is used multiple times in the same scope (that is, in visibility area), then all different types of errors will be handled correctly
  11. A desision table can be used together with an error map for error handling and informing in difficult cases

Examples of code before and after proposal

// Before proposal

package main

import (
    "errors"
    "fmt"
    "strings"
)

func capitalize(name string) (string, error) {
    if name == "" {
        return "", errors.New("no name provided")
    }
    return strings.ToTitle(name), nil
}

func main() {
    _, err := capitalize("")
    if err != nil {
        fmt.Println("Could not capitalize:", err)
        return
    }
    fmt.Println("Success!")
}

// =================================================================

// After proposal

package main

import ( // "errors" is not imported
    "fmt"
    "strings"
)

func capitalize(name string) string { // also declares and initializes an error map @capitalize, as does the operator @capitalize := map[string]bool{}
    if name == "" {
	    warning("no name provided") // new keyword. Without escape from erroneous function. Equivalent to @capitalize["no name provided"] = true
      //escape("no name provided")   // new keyword. With escape from erroneous function
        return ""
    }
    return strings.ToTitle(name)
}

func main() {
    if @capitalize["no name provided"] {  // explicit error naming in the calling function after proposal
        fmt.Println("Could not capitalize: no name provided")
        return
    }
    fmt.Println("Success!")
}

questionnaire.xlsx
questionnaire.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeLanguageChangeSuggested changes to the Go languageProposalerror-handlingLanguage & library change proposals that are about error handling.v2An incompatible library change

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions