echo
echo copied to clipboard
Is there any way for adding a group to echo.Echo or echo.Group?
Issue Description
Hello everyone! Me and my team is now working for building a web api server, and we both have different apis. So I would like to divide different api by using echo.Group
. I want to write a interface and let all developer implement it for their own need, And below is how I wanted(not actual code, won't work!)
main.go
var(
SubGroupSlice = make([]*echo.Group, 0)
)
func main() {
web := echo.New()
for _, g := range SubGroupSlice {
web.Group(g)
}
web.Start("0.0.0.0:80)
}
type CustomGroup interface{
AddGroup()
}
custom_group.go
func init(){
group := &MyGroup{ group: &echo.Group{} }
group.Build()
group.AddGroup()
}
type MyGroup struct {
group *echo.Group
}
func (g *MyGroup) Build() {
g.group.Use(XXX)
g.Get("/XXX", func(){ XXX })
}
func (g *MyGroup) AddGroup() {
SubGroupSlice = SubGroupSlice.append(g.group)
}
I know there's no such a echo.Echo.Group(g *echo.Group)
function, so I want to know if there's any way to achieve this. This allow us to easily extend the web server without interfering existing code, and since init
will executed before main()
, all added group will be available.
Checklist
- [ Y ] Dependencies installed
- [ Y ] No typos
- [ Y ] Searched existing issues and docs
Expected behaviour
Some workaround to achieve this behavior
Actual behaviour
I haven't found any
Steps to reproduce
Null
Working code to debug
Null
Version/commit
Echo V4.9.0
I think maybe I could implement a copy of echo.Echo.Add()
function but that may be too complex
And If it's no possible to achieve with echo.Echo
, echo.Group
will also help, I could just use this workaround shown below:
web := echo.New()
apiGroups := web.Group("/api")
// same as upper code
I do not think this will work - have you tested these inits? I think init is run before main()
so the Echo instance that you are adding routes from groups would not exist yet.
anyway - you really should avoid using init()
functions as they make your code harder to test and their execution order could cause problems for you. See https://www.google.com/search?q=golang+init+function+bad+practice
@aldas Yes, init()
has many shortcomings but I would like no to change the add group part of codes every time I add a new group. I now expose the echo.Echo
instance, and every subGroup's init()
will do a concurrency for-loop to wait for the echo.Echo
instance to create
I personally think you are doing it way too complicated way. I usually have "RegisterRoutes" function in package and I call it where Echo resides and if there are subgroup then they will be called inside their parent "RegisterRoutes" function
main.go
func main() {
e := echo.New()
root := e.Group("/api")
users.RegisterRoutes(root)
if err := e.Start(":8080"); err != http.ErrServerClosed {
e.Logger.Fatal(err)
}
}
Inside users
package
func RegisterRoutes(parent *echo.Group) {
group := parent.Group("/users")
group.Use(middleware.RequestID())
group.GET("/:id", func(c echo.Context) error {
return c.JSON(http.StatusOK, map[string]string{"uid": "abc123"})
})
// Register /users/files/ routes
//files.RegisterRoutes(group)
}
Inside files
package that is under users
package
func RegisterRoutes(parent *echo.Group) {
group := parent.Group("/files")
group.GET("/report", func(c echo.Context) error {
return c.String(http.StatusOK, "ok")
})
}
In that way you can test your stuff normally and do not rely on global state and complexity that init brings
@aldas This also is a good way to achieve, I will try it out and comment the result! Thank for giving a advise!
@JobberRT if you got this sorted out could you close this issue, please.
@aldas Sorry, I've figured it out, forget to close this issue... My solution is to learn golang's init
function and understand it, then I found a way to properly use the func init()
to achieve my goal