-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Application state #2670
Comments
@aldas Would you please take a look at this? |
@behnambm this seems a lot like dependency injection containers. DI is hard to test/mock. Consider this approach package main
import (
"fmt"
"github.com/labstack/echo/v4"
"net/http"
)
func main() {
e := echo.New()
g := e.Group("/users")
RegisterUserRoutes(g) // users.RegisterUserRoutes(g) <-- if it would be moved to separate package
e.Logger.Fatal(e.Start(":1323"))
}
///// in bigger application you would divide code by domains. so this is example for user related domain
// package users
type userCtrl struct {
// here you could add things that you want to access from handlers
httpClient *http.Client
}
func RegisterUserRoutes(g *echo.Group) {
userCtrl := userCtrl{httpClient: &http.Client{Timeout: 42}}
g.GET("/", userCtrl.index)
}
func (u *userCtrl) index(c echo.Context) error {
fmt.Println("Timeout :", u.httpClient.Timeout)
return c.String(http.StatusOK, "Hello, World!")
} with this approach it is easy to test these handler methods and code is cleaner etc. |
Also please see this comment #2075 (comment) |
a little bit off-topic but https://grafana.com/blog/2024/02/09/how-i-write-http-services-in-go-after-13-years/ from Mat has excellent ideas for designing around testability |
@aldas I appreciate the alternative approach you’ve suggested, especially in terms of keeping the code modular and easy to test. Here are a few points to consider:
|
I am not in favor of add this. As adding handler to structs that have dependencies as members/fields is better solution. It is cleaner and does not involve "containers for dependency injection" like things. I am well aware that in dynamically typed languages that concept is quite popular. struct fields is more go-like approach (look how standard library does things). I do not think bringing these things to strongly typed language like Go, promotes concepts that Go is known for - simplicity, readability. Dependency containers are somewhat on par with Java Annotations that is another "dark hidden magic" which is not easy to reason just by looking at code.
client, ok := c.Echo().State.Get("myClient")
httpClient, ok := client.(*http.Client)
if ok {
fmt.Println("Timeout :", httpClient.Timeout)
} vs func (u *userCtrl) index(c echo.Context) error {
fmt.Println("Timeout :", u.httpClient.Timeout) this is far superior approach if you have more than 1 dependency that you need to access as you do not need to cast+check anything as struct is strongly typed.
client, ok := c.Echo().State.Get("myClient")
httpClient, ok := client.(*http.Client) you would do httpClient, ok :=c.Get("myClient").(*http.Client)
client, ok := state.Get("myClient")
There is not need to make this Echo field/feature. |
If it doesn’t make sense to add this feature to Echo, I’ll go ahead and close the issue. |
Application state
This proposal seeks to introduce an Application State Management feature in Echo.
This feature will enable the ability to access a store application wide. Mmiddlewares and request handlers will be able to access this store because they both have access to
Echo
struct. The state's data will not change from request to request.Similar functionality is available in other frameworks, such as FastAPI.
API
Set(key string, val any)
Get(key string) (any, bool)
We need to discuss about some cases that needs to be considered in the API design.
For example, should we override the already existing data? Or return an error?
Sample
The text was updated successfully, but these errors were encountered: