Skip to content

Instantly share code, notes, and snippets.

@marlonche
Last active April 25, 2022 03:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marlonche/4e5d4e5aec0555958ec1f181991325f6 to your computer and use it in GitHub Desktop.
Save marlonche/4e5d4e5aec0555958ec1f181991325f6 to your computer and use it in GitHub Desktop.

How about separating check and handle as follows:

  1. handle can just works like defer as the draft suggested(called after return in reversed order of definition), and the magic identifier err could be changed to any error varible decalared, not the result of check.

  2. The error result as the last return value of a function should not be omitted in the presence of check.

  3. The return statements in handle just return the handle scope, not the function scope.

  4. Restrict functions to use named result parameters when using check.

func CopyFile(src, dst string) (err error) {
  var err1, err2 error
  handle err1, err2 { //at least one is non-nil
    ...
  }
  handle err1 {
    err = fmt.Errorf("prepare copy %s %s: %v", src, dst, err1)
  }
  handle err2 {
    err = fmt.Errorf("copy %s %s: %v", src, dst, err2)
  }

  r, err1 := check os.Open(src)
  defer r.Close()

  w, err1 := check os.Create(dst)
  handle err2 {
    w.Close()
    os.Remove(dst)
  }
  
  err2 = check io.Copy(w, r)
  // or need additional handling before returning to handles above
  if err2 = io.Copy(w, r); err2 != nil {
    ... special handling ...
    return
  }

  err2 = check w.Close()
}

Or in the simplest case:

func CopyFile(src, dst string) (err error) {
  handle err {
    err = fmt.Errorf("copy %s %s: %v", src, dst, err)
  }

  r, err := check os.Open(src)
  defer r.Close()

  w, err := check os.Create(dst)
  handle err {
    w.Close()
    os.Remove(dst)
  }

  err = check io.Copy(w, r)

  err = check w.Close()
}

In this way, check works just equivalently to:

if err != nil {
  return
}

handle works just equivalently to:

defer func() {
  if err != nil {
  }
}()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment