introduction
I've seen a lotgolang
The developers of the community, especially those attracted by its simplicity,golang
There are some quick judgments on how things should be handled.
One of the things is error handling. Since most language developers are fromOOP
Background, they are used to handling exceptions, or the concept of "throwing" exceptions to stop the flow of the current application, and they mostly think that this is alsogolang
The way we have to stop the flow of our application in case of an error. They were wrong!
Don't abuse your tools
I've seen a lot, and I did this before. Whenever an unexpected situation occurs, use it(1)
, and then move on. Well, this is not the right way to use go!
I understand why this is widely used, because most of the early onesgolang
Applications are just terminal tools, and many of these tools have been used.sh
To build the executable file, we used to just exit 1; to indicate that something unexpected happened just now and we wanted to exit.
We brought this habit to our golang simple terminal application and then to complex applications, which is just another Cargo Cult Programming. I highly encourage you to be very careful when you have to do this, because it is:
- As your application grows, it is very difficult to maintain.
- Most importantly, it is impossible to unit test such a code, which clearly shows its uncleanness.
- Exiting in this way will prevent the execution of any delayed operations from being executed and your program will be terminated immediately, which may lead to resource leakage. Please consider this example:
func main() { dbConnection := ("...") defer () // this operation won't be executed! entity := Entity{} err := (entity) if err != nil { (1) } }
Consider passing your error
The error is justgolang
Another type in which you must use to control the execution flow of your program.
In order to do this, we have to propagate these errors throughout the program until the appropriate processing point.
Consider an HTTP API that manages orders, we want to prohibit customers from placing orders under specific conditions, such as:
package order // package errors var ( UnableToShipToCountry = ("unable to ship order to the requested country") ) type Order struct { // ... order fields } type OrderRepo struct { DB db // ... } func newOrderFromRequest(o OrderRequest) (Order, error) { if != "DE" { return UnableToShipToCountry } // ... the creation logic return Order{...}, nil } func (r *OrderRepo)PlaceOrder(o OrderRequest) error { order, err := newOrderFromRequest(o) if err != nil { // don't handle the error here, its handling may differ return err } // ... db transaction may also return an error return (order) }
In ourhttp package
middle:
package http ("/order", func (w , r *) { orderRequest := createOrderRequest(r) err := (orderRequest) if (err, ) { () return } if err != nil { // this error in case of DB transaction failure () return } // ... () })
Customize your errors
We can create our own custom error value and use it in our program while considering adding some useful information like error tracking which may add a beneficial value to our logs, especially during debugging.
type AppErr struct { msg string code int trace string } func (e AppErr) Error() string { return ("Msg: %s, code: %d, trace:\n %s", , , ) } func NewAppErr(msg string, code int) AppErr { stackSlice := make([]byte, 512) s := (stackSlice, false) return AppErr{msg, code, ("\n%s", stackSlice[0:s])} }
And we have such a use case in a package:
package admin func A() error { return b() } func b() error { return NewAppErr("error from b function!", 3) }
:
func main() { err := () (err) }
The logged error message will be:
Msg: error from b function!, code: 3, trace:
goroutine 1 [running]:
./cmd/app/({0x1f42b0, 0x17}, 0x7)
./cmd/app/error/:16 +0x35
./cmd/app/(...)
./cmd/app/admin/**:12**
./cmd/app/(...)
./cmd/app/admin/**:8**
()
./cmd/app/**:10** +0x8d
You can also consider turning off your tracking print in production, or checking for other configuration values.
The above is the detailed explanation of the Go language's elegant processing error tools and techniques. For more information about Go language processing error tools, please pay attention to my other related articles!