Do I understand correctly that "last return value is error" is purely 
convention and there is no formal error handling in current go?

My instinct is to leverage the 'else' keyword along with the notion of a 
"stock error whose return list's last element is type error with value != 
nil.

  func not_stock() (int, interface{})
  func stock() error
  func stock() (int, error, string, float, error, error, error)
  func not_stock() (error, error, error, int)
  func stock() (error, error)

Any other type of error handling can still be handled as the user wishes, 
stock errors simply provide syntax to lean into, and that syntax would be: 
 
    [ <assignment> ] <call expr> ast.ELSE <block statement>

e.g.

    file, err := io.Open(file) else {
      return nil, err
    }
    fh.Close() else {
      panic("close call failed")
    }

Equivalent to:

    file, err := io.Open(file)
    if err != nil {
      return nil, err
    }
    if err := fh.Close(); err != nil {
      panic("close call failed")
    }

One of the current nuisances of error handling is that it can break the 
clean flow of variable assignments, forcing you to add separate 
declarations or scopes. Given a function

   func NewStruct() (s *Struct, sz int, err error)

you typically have two very different lifespans for the return values

   s, sz, err := NewStruct()
   if err != nil {  // last reference to err in function

vs

    if s, sz, err := NewStruct(); err != nil {
      panic(err)
    } else {
      // to access s and sz
    }

or

    var (
      s *Struct
      sz int
      err error   // but literally only for one line
    )
    if s, sz, err = NewStruct(); err != nil {
      panic(err)
    }

Using the else construct always allows the shorter form, which is at least 
consistent:

    // not a sub-clause so s, sz and err introduced in current scope level.
    s, sz, err := NewStruct() else {
      panic(err)
    }

The fly in the ointment here is ... where does the error go if you don't 
mention it?

    fh.Close() else {
      panic(?what?)
    }

the lazy option would be `_`

    fh.Close() else {
      fmt.Errorf("unexpected close failure: %s", _)
      err := _
      panic(err)
    }

But I think we can avoid the path of perl, and simply require capture if 
you want the value surfaced.

    err := fh.Close() else {
      panic(err)
    }

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/5962bf1d-d81f-4ab2-b710-cafbecdeaf78n%40googlegroups.com.

Reply via email to