How would one go about adding a method to a struct that is a different file? This is what I've tried so far but it doesn't seem to be working.
// ./src
package routes
type App struct{
}
func (a *App) initializeRoutes() {
a.Subrouter.HandleFunc("/products", a.getSomething).Methods("GET")
}
// ./src/controller
package routes
func (a *App) getSomething(w http.ResponseWriter, r *http.Request){
...
}
They are in the same package.
They are not in the same package. A Go package has both a name and a path. They're both named routes
but they have different paths. The actual packages are routes
and controller/routes
. The result is subdirectories are different packages.
See Package Names on the Go Blog for more information.
Since they're in different packages, they can only access each other's public members and exported methods. You can't monkey patch someone else's package or interface in Go. This is by design to keep all the functionality of a package in one place, no action-at-a-distance.
You have options. You could put all methods of routes
into a single package. If they all belong together, there's no need to split it up into multiple files.
If they don't really belong together, you can write a new struct with routes embedded into it and define new methods on that. Then you can access either the wrapper struct to get your added methods, or its embedded struct to get routes
' methods. See this answer for an example.
But really I think you need to think about how your code is arranged. The App
probably shouldn't be defined by the routes
package, they should be separate. Instead, Go prefers a has-a relationship. App
would contain an instance of routes.Route
.
You'd rearrange your code tree like so:
app/
app.go
app_test.go
routes/
routes.go
routes_test.go
Note that rather than having it all in src/
it's now contained in its own project directory. app.go
would look something like this.
// src/app/app.go
package app
import(
"app/routes"
"fmt"
"net/http"
)
type App struct {
routes routes.Route
}
func (a *App) initializeRoutes() {
a.routes.AddRoute("/products", a.getSomething)
}
func (a *App) getSomething(w http.ResponseWriter, r *http.Request) {
fmt.Println("Something!")
}
Notice how we're delegating responsibility to adding a route to a.routes
rather than having App
do it itself. This avoids the desire to smash all functionality into one ginormous package. routes.Route
would be defined in app/routes/routes.go
.
// src/app/routes/routes.go
package routes
import "net/http"
// A type specifying the interface for route handlers.
type RouteHandler func(w http.ResponseWriter, r *http.Request)
type Route struct {
handlers map[string]RouteHandler
}
func (r *Route) AddRoute(path string, handler RouteHandler) {
r.handlers[path] = handler
}
Now all routes has to worry about is handling routes. It doesn't know anything about your specific application logic.
I was trying to get my http.res & http.req functions in a controllers file.
Now that we've rearranged the file structure, you can do that. You can, if you like, define app/controllers.go
to organize your code.
// src/app/controllers.go
package app
import(
"fmt"
"net/http"
)
func (a *App) getSomething(w http.ResponseWriter, r *http.Request) {
fmt.Println("Something!")
}
app/app.go
and app/controllers.go
are in the same package. They have the same path and the same name. So app/controllers.go
can add methods to App
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With