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

feat(tag): Tag feature experimentally #14

Merged
merged 6 commits into from
Jan 6, 2025
Merged

feat(tag): Tag feature experimentally #14

merged 6 commits into from
Jan 6, 2025

Conversation

m-mizutani
Copy link
Owner

@m-mizutani m-mizutani commented Jan 4, 2025

Motivation

There are use cases where we need to adjust the error handling strategy based on the nature of the error. A clear example is an HTTP server, where the status code to be returned varies depending on whether it's an error from a downstream system, a missing resource, or an unauthorized request. To handle this precisely, you could predefine errors for each type and use methods like errors.Is in the error handling section to verify and branch the processing accordingly. However, this approach becomes challenging as the program grows larger and the number and variety of errors increase.

goerr provides a With method that allows parameters to be set on errors. However, specifying parameters as strings each time raises concerns about typos, leaving room for errors during development.

This pull request (PR) introduces a mechanism to prevent typos by predefining Tags and only accepting that type, thus enhancing reliability in development.

Example

var (
	ErrTagSysError   = goerr.NewTag("system_error")
	ErrTagBadRequest = goerr.NewTag("bad_request")
)

func handleError(w http.ResponseWriter, err error) {
	if goErr := goerr.Unwrap(err); goErr != nil {
		switch {
		case goErr.HasTag(ErrTagSysError):
			w.WriteHeader(http.StatusInternalServerError)
		case goErr.HasTag(ErrTagBadRequest):
			w.WriteHeader(http.StatusBadRequest)
		default:
			w.WriteHeader(http.StatusInternalServerError)
		}
	} else {
		w.WriteHeader(http.StatusInternalServerError)
	}
	_, _ = w.Write([]byte(err.Error()))
}

func someAction() error {
	if _, err := http.Get("http://example.com/some/resource"); err != nil {
		return goerr.Wrap(err, "failed to get some resource").WithTags(ErrTagSysError)
	}
	return nil
}

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if err := someAction(); err != nil {
			handleError(w, err)
			return
		}
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte("OK"))
	})

	http.ListenAndServe(":8090", nil)
}

tag.go Fixed Show fixed Hide fixed
examples/tag/main.go Fixed Show fixed Hide fixed
examples/tag/main.go Fixed Show fixed Hide fixed
@m-mizutani m-mizutani merged commit 50722e8 into main Jan 6, 2025
5 checks passed
@m-mizutani m-mizutani deleted the feat/tags branch January 6, 2025 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant