4 ms·
I don't think it would be fair to say that the Go community optimizes for productivity over good software development practices. In fact, there's been a good pu
by zalmoxes 10y ago
I don't think it would be fair to say that the Go community optimizes for productivity over good software development practices. In fact, there's been a good push in the community lately to talk about application design and what it means for code to be good/not good.
* https://github.com/marcusolsson/gouk16-slides/blob/master/building-an-enterprise-service-in-go.pdf https://github.com/marcusolsson/gouk16-slides/blob/master/bu...
* https://peter.bourgon.org/go-best-practices-2016/ https://peter.bourgon.org/go-best-practices-2016/
* http://dave.cheney.net/2016/08/20/solid-go-design http://dave.cheney.net/2016/08/20/solid-go-design
However, as a Go developer I'm finding that a lot of examples/tutorials and github projects are taking shortcuts when it comes to program design and how dependencies(loggers, config, db handlers) are being passed around.
https://peter.bourgon.org/go-best-practices-2016/#program-design https://peter.bourgon.org/go-best-practices-2016/#program-de...
IMO it's a sign of Go still being a relatively new language. Despite the language existing for ~6 years now, we're only discovering some best practices today.
- infogulch 10y agoI've actually built out a concept to address this: https://github.com/infogulch/inject https://github.com/infogulch/inject Call `di := inject.New(db, logger, tmpl, ...)` then you can call `di.Inject(myfunction)` which just calls the function with the values passed to New and returns the result. "YAWN" Here's the key: `myfunction` shouldn't just execute, it should return a closure over the injected values that can be called later. E.g. func home(t *template.Template, db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { var tm string db.QueryRow(`select datetime('now')`).Scan(&tm) t.ExecuteTemplate(w, "home.html", tm) } } Now with `fn := di.Inject(home)`, fn is a plain old http.HandlerFunc, it has access to its' dependencies (and just those dependencies) without global state, and there is no reflection in the hot path. Of course, you could use this technique manually: `fn := home(tmpl, db)` but inject can be integrated with your framework and you don't have to make any changes to code. It's also designed to not require the framework to depend on the reflect package, it can just define and accept the Inject interface.