Live data from Hacker News

Some Go web dev notes

jvns.ca

51–60 of 154 posts

Re: Some Go web dev notes

#51
post #29

There are some good tips here. As for sqlc, I really wanted to like it, but it had some major limitations and minor annoyances last time I tried it a few months ago. You might want to go through its list of issues[1] before adopting it. Things like no support for dynamic queries[2], one-to-many relationships[3], embedded CTEs[4], composite types[5], etc. It might work fine if you only have simple needs, but if you ev…

I agree that sqlc has limits, but for me it is great because it takes care of 98% of the queries (made up number) and keeps them simple to write. I can still write manual queries for the rest of them so it's still a net win.

Re: Some Go web dev notes

#52
post #2

> In general everything about it feels like it makes projects easy to work on for 5 days, abandon for 2 years, and then get back into writing code without a lot of problems. To me this is one of the most underrated qualities of go code. Go is a language that I started learning years ago, but did't change dramatically. So my knowledge is still useful, even almost ten years later.

> Go is a language that I started learning years ago, but did't change dramatically.

A lot of people underrate that quality I feel. C had that quality but pushed it to neurotic levels where it would change so slowly even when it needed to do it faster. Other language in contrast change too fast and try to do too many things at once.

You do not often get credit for providing boring, stable programs that work. I hope they continue to do it this way and do not get seduced into overloading the language.

We have a lot of fast moving languages already, so having one that moves slowly increases potential choice.

Re: Some Go web dev notes

#53
post #49

the whole gobin / gopath thing was annoying as a beginner: I just want to build this module and use that local module go build ./... Goes where ?

I believe it is recommended to not use gobin/gopath anymore.

go test ./… tests all files in the project, so I assume build does something similar.

Re: Some Go web dev notes

#54
post #7
post #2

> In general everything about it feels like it makes projects easy to work on for 5 days, abandon for 2 years, and then get back into writing code without a lot of problems. To me this is one of the most underrated qualities of go code. Go is a language that I started learning years ago, but did't change dramatically. So my knowledge is still useful, even almost ten years later.

I agree but those first 5 days are going to be a mixed bag as you pick through libraries for logging, database drivers, migrations, as well as project organization, dependency injection patterns for testing, organize your testing structure, and more. If you have a template to derive from or sufficient Go experience you'll be fine, but selecting from a grab bag of small libraries early on in a project can be a distrac…

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.

Re: Some Go web dev notes

#55
post #20

> I learned the hard way that if I don’t do this then I’ll get SQLITE_BUSY errors from two threads trying to write to the db at the same time. OK, here's a potentially controversial opinion from someone coming into the web + DB field from writing operating systems: 1. Database transactions are designed to fail Therefore 2. All database transactions should done in a transaction loop Basically something like this: http…

I always see SQLite as recommended, but every time I look into it there are some non-obvious subtleties around txn lock, retry behavior, and WAL mode. By default if you don't tweak things right getting frequent SQLITE_BUSY errors seems to occur at non-trivial QPS. Is there a place that documents what the set-and-forget setting should be?

_journal_mode=wal&_busy_timeout=200 seems to work well enough.

Re: Some Go web dev notes

#56
Other note

Sooner or later you will hit html/template, and realize it's actually very weird and has a lot of weird issues.

Don't use html/template.

I grew to like Templ instead

Re: Some Go web dev notes

#57
post #48
post #7

Earlier quoted context omitted.

I agree but those first 5 days are going to be a mixed bag as you pick through libraries for logging, database drivers, migrations, as well as project organization, dependency injection patterns for testing, organize your testing structure, and more. If you have a template to derive from or sufficient Go experience you'll be fine, but selecting from a grab bag of small libraries early on in a project can be a distrac…

I think 80% of this is people coming to Go from other languages ( everybody comes to Go from some other language) and trying to bring what they think was best about that language to Go. To an extent unusual in languages I've worked in, it's idiomatic in Go to get by with what's in the standard library. If you're new to Go, that's what you should do: use standard logging, just use net/http and its router, use standard…

Go these days has had a good few stdlib improvements that reduce your reliance on third party libraries even further.

The http router now handles path parameters and methods, so you might just pull in a library to run a middleware stack.

There is structured logging in the stdlib, which works with the existing log package for an easy transition.

The thing I’ve struggled with is structuring a project nicely, what with the way modules work, especially for services that aren’t exactly ‘micro’, and especially when the module and workspace system is still pretty unintuitive.

Re: Some Go web dev notes

#58
post #29

There are some good tips here. As for sqlc, I really wanted to like it, but it had some major limitations and minor annoyances last time I tried it a few months ago. You might want to go through its list of issues[1] before adopting it. Things like no support for dynamic queries[2], one-to-many relationships[3], embedded CTEs[4], composite types[5], etc. It might work fine if you only have simple needs, but if you ev…

It gets mentioned a lot in the context of database/sql and sqlc, but Jet has been a great alternative so far, most notably because of its non-issue with dynamic queries support.

https://github.com/go-jet/jet/

Re: Some Go web dev notes

#59
post #2

> In general everything about it feels like it makes projects easy to work on for 5 days, abandon for 2 years, and then get back into writing code without a lot of problems. To me this is one of the most underrated qualities of go code. Go is a language that I started learning years ago, but did't change dramatically. So my knowledge is still useful, even almost ten years later.

I've picked up some Go projects after no development for years, including some I didn't write myself as a contractor. It's typically been a fairly painless experience. Typically dependencies go from "1.3.1" to "1.7.5" or something, and generally it's a "read changelogs, nothing interesting, updating just works"-type experience.

On the frontend side it's typically been much more difficult. There are tons of dependencies, everything depends on everything else, there are typically many new major releases, and things can break in pretty non-obvious ways.

It's not so much the language itself, it's the ecosystem as a whole. There is nothing in JavaScript-the-language or npm-the-package-manager that says the npm experience needs to be so dreadful. Yet here we are.

Re: Some Go web dev notes

#60

Other note Sooner or later you will hit html/template, and realize it's actually very weird and has a lot of weird issues. Don't use html/template. I grew to like Templ instead

stdlib templates are a bit idiosyncratic and probably not the easiest to start with, but they do work and don't have "weird issues" AFAIK. What issues did you encounter?
Post reply on HN