This part cover some of the implementation decisions taken along the development process.
Handler functions has 1 parameter:
func (c *golax.Context) {
}
Why not w
, r
and c
and maintain developer compatibility?
We would ended up with the following signature:
func (w http.ResponseWriter, r *http.Request, c *golax.Context) {
}
Old code is not going to work by doing copy&paste, but you only have to replace:
w
byc.Response
r
byc.Request
Making this decision is hard but c *golax.Context
is much easier to remember and to write.
About code readability, w.Write(...)
is shorter but c.Response.Write(...)
is more semantic.
Changing Middleware vs Interceptor is a semantic decision to break up with Sinatra styled frameworks.
Typical middlewares should call to next()
to continue chaining execution. On the other hand, an interceptor has two parts Before
and After
and you don't have to call any next()
or similar. It follows the Hollywood Principle known as "Don't call us, we'll call you".
Each node in the routing hierarchy executes all its parent nodes interceptors. Why?
This is the desired behaviour for the 95% of the cases or even more. With several advantages:
- You don't have to repeat the interceptor (or middleware) in every endpoint.
- You get prettier, more readable and understandable code.
- Avoid human errors.
Support for custom methods is a routing feature, you are free to use or not. It does not mean coupling with other libraries or adding non-routing responsibilites.
If you do not use custom methods (.Operation("your-custom-method")
) the router behaves
exactly as if it does not support them. In other words, it is backwards compatible.