Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: Error handling with try-with-resources #29120

Closed
eau-de-la-seine opened this issue Dec 6, 2018 · 2 comments
Closed

proposal: Go 2: Error handling with try-with-resources #29120

eau-de-la-seine opened this issue Dec 6, 2018 · 2 comments
Labels
error-handling Language & library change proposals that are about error handling. FrozenDueToAge Proposal
Milestone

Comments

@eau-de-la-seine
Copy link

eau-de-la-seine commented Dec 6, 2018

Currently:

func CopyFile(src, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("copy %s %s: %v", src, dst, err)
	}
	defer r.Close()

	w, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("copy %s %s: %v", src, dst, err)
	}

	if _, err := io.Copy(w, r); err != nil {
		w.Close()
		os.Remove(dst)
		return fmt.Errorf("copy %s %s: %v", src, dst, err)
	}

	if err := w.Close(); err != nil {
		os.Remove(dst)
		return fmt.Errorf("copy %s %s: %v", src, dst, err)
	}
}

Proposal inspired by Java 7's try-with-resources:

func CopyFile(src, dst string) error {
	check 
		r, err1 := os.Open(src); // Related to the first catch block
		w, err2 := os.Create(dst); // Related to the second catch block, if the second catch block does not exists then the last existing catch block
		_, err3 := io.Copy(w, r); // Related to the third catch block, if the third catch block does not exists then the last existing catch block
	{
		os.Remove(dst)
	} catch _ {
		return fmt.Errorf("copy %s %s: %v", src, dst, err1)
	} catch _ {
		// This catch block can be optional 
		return fmt.Errorf("copy %s %s: %v", src, dst, err2)
	} catch _ {
		// This catch block can be optional 
		return fmt.Errorf("copy %s %s: %v", src, dst, err3)
	}
}

Error messages are the same format, simplified version:

func CopyFile(src, dst string) error {
	check 
		r, err1 := os.Open(src);
		w, err2 := os.Create(dst);
		_, err3 := io.Copy(w, r);
	{
		os.Remove(dst)
	} catch err { // Error pointer on err1, or err2, or err3
		return fmt.Errorf("copy %s %s: %v", src, dst, err)
	}
}

Notes:

  • The Open(), Create(), and Copy() functions signature must be function() T, error where T is a generic type which implements a Close() function.
  • check executes instructions one by one and implicitely does the err != nil operation, if err isn't nil, the related catch block is executed. Syntactic sugar: If the related catch block does not exists, try to execute the last catch block.
  • You can add a "finally" block to this proposal.
  • Drawback: This technique does not handle the last if err := w.Close(); err != nil { ... } block, but should a close method return an error? Even Java's or C#'s close function doesn't return anything :)
@gopherbot gopherbot added this to the Proposal milestone Dec 6, 2018
@agnivade
Copy link
Contributor

agnivade commented Dec 6, 2018

Hi @eau-de-la-seine - thank you for this proposal !

All feedback on any new error handling design is being currently collated here - https://github.com/golang/go/wiki/Go2ErrorHandlingFeedback. I would request you to create a doc or a gist and add a link to that wiki page.

Thank you.

@agnivade agnivade closed this as completed Dec 6, 2018
@eau-de-la-seine
Copy link
Author

eau-de-la-seine commented Dec 6, 2018

Done (Gist link here), thank you :)

@bradfitz bradfitz added the error-handling Language & library change proposals that are about error handling. label Oct 29, 2019
@golang golang locked and limited conversation to collaborators Oct 28, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
error-handling Language & library change proposals that are about error handling. FrozenDueToAge Proposal
Projects
None yet
Development

No branches or pull requests

4 participants