I'm trying to come up with a very compact way of handling problems that may arise in HTTP requests for a REST API.
There are many conditions that I need to test for, and many potential error responses for the failure of any of these conditions.
I've gotten my handling flow down to something that looks similar to the following:
// Error is actually a method on some struct, so it's only relevant for demonstration purposes.
func Error(w http.ResponseWriter, status int, message string) {
// Lots of stuff omitted
w.WriteHeader(status)
w.WriteJson(r)
}
func HandleSomething(w http.ResponseWriter, r *http.Request) {
if someCondition != true {
Error(w, 500, "Some error occurred!")
return
}
if someOtherCondition != true {
Error(w, 500, "Some other error occurred!")
return
}
if yetAnotherCondition != true {
Error(w, 500, "Yet another error occurred!")
return
}
if andFinallyOneLastCondition != true {
Error(w, 500, "One final error occurred!")
return
}
// All good! Send back some real data.
w.WriteJson(someObject)
}
Since there are often 5-10 conditions that I need to test for, and other errors that can arise during other operations, it would be nice to be able to compact it to the following:
func HandleSomething(w http.ResponseWriter, r *http.Request) {
if someCondition != true {
return Error(w, 500, "Some error occurred!")
}
if someOtherCondition != true {
return Error(w, 500, "Some other error occurred!")
}
if yetAnotherCondition != true {
return Error(w, 500, "Yet another error occurred!")
}
if andFinallyOneLastCondition != true {
return Error(w, 500, "One final error occurred!")
}
// All good! Send back some real data.
w.WriteJson(someObject)
}
However, the Go compiler doesn't like this.
It complains both that I'm trying to use the result of Error()
as a value, and that I'm trying to return too many arguments. The exact error messages are:
foo.go:41: bar.Response.Error(400, "InvalidRequest", "Error decoding request") used as value
foo.go:41: too many arguments to return
But both Error()
and HandleSomething()
have the same return signature (e.g. they both return nothing), so shouldn't this work?
It's important that each if
statement contains a return
, because the function should be exited immediately. If Error()
could somehow stop the execution of the calling function, that would also work for me. Sort of like testing.FailNow()
, but I believe that relies on Goroutines.
As an aside: I realize that these aren't really "void" functions, but couldn't think of a more appropriate name. Is there a proper name for functions that return nothing in Go?