|
I really think the library search is more of something you inherit from other languages, though database drivers are something you need to go looking for. The standard library has an adequate HTTP router (though I prefer grpc-gateway as it autogenerates docs, types, etc.) and logger (slog, but honestly plain log is fine). For your database driver, just use pgx. For migrations, tern is fine. For the tiniest bit of sugar around scanning database results into structs, use sqlx instead of database/sql. I wouldn't recommend using a testing framework in Go: https://go.dev/wiki/TestComments#assert-libraries Here's how I do dependency injection: func main() {
foo := &Foo{
Parameter: goesHere,
}
bar := &Bar{
SomethingItNeeds: canJustBeTypedIn,
}
app := &App{
Foo: foo,
Bar: bar,
}
app.ListenAndServe()
}
If you need more complexity, you can add more complexity. I like "zap" over "slog" for logging. I am interested in some of the DI frameworks (dig), but it's never been a clear win to me over a little bit of hand-rolled complexity like the above.A lot of people want some sort of mocking framework. I just do this: - func foo(x SomethingConcrete) {
- x.Whatever()
- }
+ interface Whateverer { Whatever() }
+ func foo(x Whateverer) {
+ x.Whatever()
+ }
Then in the tests: type testWhateverer {
n int
}
var _ Whateverer = (*testWhateverer)(nil)
func (w *testWhateverer) Whatever() { w.n++ }
func TestFoo(t *testing.T) {
x := &testWhateverer{}
foo(x)
if got, want := x.n, 1; got != want {
t.Errorf("expected Whatever to have been called: invocation count:\n got: %v\n want: %v", got, want)
}
}
It's easy. I typed it in an HN comment in like 30 seconds. Whether or not a test that counts how many times you called Whatever is up to you, but if you need it, you need it, and it's easy to do. |
Only exception is you should use my migration library [0] instead of tern — you don't need down migrations, and you can stop worrying about migration number conflicts.
One other suggestion I'll make is you probably at some point should write a translation layer between your API endpoints and the http.Handler interface, so that your endpoints return `(result *T, error)` and your tests can avoid worrying about serde/typeasserting the results.
[0] https://github.com/peterldowns/pgmigrate