Skip to content

proposal: Go 2: improve error handling syntax #36390

Closed
@cmidt-veasna

Description

@cmidt-veasna

Salute to everyone here, for the pass few weeks, I've read through all error handling proposal and I know most of them is likely to be rejected at the moment however I would like to put my idea here to help shape up the future if possible.

This proposal aiming to keep old syntax relevant and maintain compatibility.

This proposal utilize 2 new symbols ? and => with an existing symbol ! to improve error handling and various part of the language.

  • Use exclamation mark "!" symbol if we want to panic application
  • Use question mark "?" symbol if we want to return from the function
  • Use "=>" symbol to provide custom error or wrapped error

Acceptant Syntax

  1. Symbol ! and ? is allow to use with the last variable in assign or define statement only.
  2. The last variable must be a bool or an error type where bool would only work with map, channel and casting
    • err? := firstPatient()
    • patient, ok! := dictPatient["boob"]
    • number, ok? := it.(int)
    • patient, ok? := <- patientQueue
  3. Symbol ? is allow to use in function or closure where return signature contain error type however it's not required when using with channel, casting or map
  4. Symbol ! is not allow to use with channel
  5. Both symbol is not allow to use in for loop (Range) and if initial statement.

Syntax pattern: var1, var2(?|!) := val1, val2 [=> error]

Note: To distinguish with a different opertor "!=", it required to have a whitespace after either ? or ! which mean statement err?:= firstPatient() is invalid.

patient, err? := findPatient(name)
// equivalent to
patient, err := findPatient(name)
if err != nil {
    return err
}

id := "mly123"
patient, ok! := dictPatient[id] =>
        fmt.Errorf("Patient id %s not found", id)
// equivalent to
id := "mly123"
patient, ok := dictPatient[id]
if !ok {
    panic(fmt.Errorf("Patient id %s not found", id))
}

Compiler accepted

// channel usage
ch := make(chan bool)
// return as soon as channel close
b, ok? := <- ch
select {
// return as soon as channel close
case b, ok? := <- ch:
}

// suppose findPatient return a patient and an error
// return as soon as err is not nil
patient, err? := findPatient(name)
patient, err? := findPatient(name) => fmt.Errorf("cannot find patient name %s: %w", name, err)

patient, err! := findPatient(name)


// panic as soon as patient name "boob" is not exist in map "dictPatient"
patient, ok! := dictPatient["boob"]
// return as soon as patient name "boob" is not exist
patient, ok? := dictPatient["boob"] => &MyError{ Name: "boob", Message: "not existed" }

name, ok? := iPatient.(string)
// we can use error message generated by compiler instead.
name, ok! := iPatient.(string) => fmt.Errorf("iPatient is not a string")

// only ! can be use outside of function or closure
package foo
var patient, err! = findPatient("some name")

// ! can be use with error type in "init" function
package foo
func init() {
    config, err! := parseConfiguration("path to file")
    number, ok? := s.(int)
    number, ok! := s.(int)
}

Compiler rejected

// channel do not accept ! mark nor custom error or wrapped error
b, ok! := <- ch
b, ok? := <- ch => fmt.Errorf("error message")

// wrong type and need to be use with last variable
patient?, err = findPatient(name)
// allow one usage only
patient?, err! = findPatient(name)

// suppose getPatient return a patient and a bool
// ***
// *** it's possible to make this statement valid if we treat 
// *** this statement the same as type casting statement.
patient, existed? = getPatient(id)

// ? only allow to use within function or closure
package foo
var patient, err? = findPatient("some name")

// ? is not allow to use with error type in init function or function that
// does not have error type as part of return signature
package foo
func init() {
    config, err? := parseConfiguration("path to file")
}

Thought

I've experimented with this syntax and my thought is, the syntax is short however it probably add a bit complexity to the compilation as the transformation or code generation must be done after a full type check is completed.

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