There isn't any way to do what you want since packages are denoted by the import path, which is tied to the directory structure. One directory, one package (the exception being package routes_test
, for testing purposes).
In my observation many Go programmer seem to prefer larger packages, rather than subdividing things in smaller packages. I find that for e.g. HTTP handlers this is usually fine, as they tend to be fairly small functions, with the bulk of the logic being somewhere else, such as a "service", "model", or whatever you're naming it in your architecture.
This is a matter of personal taste though, and some programmers do subdivide their code in to smaller packages by putting them in subdirectories, like you've done in your example.
Another option might be to divide things in to structs:
routes/login.go
:
package routes
type LoginHandler struct {}
func (h LoginHandler) Login(r *http.Request, w http.ResponseWriter) {
// ...
}
// .. other methods related to Login etc. ..
routes/register.go
:
package routes
type RegisterHandler struct {}
func (h RegisterHandler) NewUser(r *http.Request, w http.ResponseWriter) {
// ...
}
// .. other methods related to registration etc. ..
And then register that with e.g.:
login := routes.Login{}
router.HandleFunc("/login", login.Login).Methods("GET")
register := routes.Register{}
router.HandleFunc("/register", register.NewUser).Methods("GET")
You can also add a Mount()
or Routes()
method to the LoginHandler
and RegisterHandler
types like so:
type LoginHandler struct {}
// Mount the routes.
func (h LoginHandler) Mount(router someRouterType) {
router.HandleFunc("/login", h.Login).Methods("GET")
}
Instead of putting them all in main.go
. This, again, is a matter of personal taste.
This is also a convenient way to inject common dependencies, such as a database connection.