[HN Gopher] Some Go web dev notes
       ___________________________________________________________________
        
       Some Go web dev notes
        
       Author : tosh
       Score  : 242 points
       Date   : 2024-09-29 14:36 UTC (8 hours ago)
        
 (HTM) web link (jvns.ca)
 (TXT) w3m dump (jvns.ca)
        
       | voigt wrote:
       | > 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.
        
         | tmpz22 wrote:
         | 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 distraction that
         | slows down feature development significantly.
         | 
         | I love Go but for rapid project development, like working on a
         | personal project with limited time, or at a startup with
         | ambitious goals, Go certainly has its tradeoffs.
        
           | joshlemer wrote:
           | I stumbled on this Go starter project that has enough
           | batteries included to get you started I think. You might find
           | it useful
           | 
           | https://github.com/mikestefanello/pagoda
        
             | tmpz22 wrote:
             | Right and mikestefanello/pagoda seems like a comprehensive
             | framework combining the labstack/echo/v4 routing framework
             | and entgo.io/ent "ORM" - among other things like HTMX and
             | Bulma.
             | 
             | That is a highly opinionated grouping of tools that gets
             | you to a poor persons version of a full stack framework
             | that many in the Go community would flat out reject.
        
               | leetrout wrote:
               | I really don't understand the hate for a framework in
               | "the community". I had stayed away from Go for about 3
               | years and I posted on r/golang asking if anything had
               | popped up like a django in go and got nothing but hate.
               | 
               | I chock it up to people enjoy writing the same boiler
               | plate stuff over and over in their paid jobs where they
               | have the time to do it.
               | 
               | To your point, I've got my own set of libraries that I
               | think are The Best(tm) for all my reasons that at least
               | keep me productive.
               | 
               | Echo for the routing... sqlc for the db interface... I
               | actually _love_ gomega and ginkgo for BDD but it makes
               | people actually angry so I settle for testify and for
               | logging we have slog now but I usually grab the logging
               | lib from charm bracelet for nice colorized, leveled
               | logging.
        
               | cgg1 wrote:
               | The best thing I've found is beego:
               | https://github.com/beego/beego
               | 
               | Not affiliated in any way, but to me it's better than
               | most of the alternatives
        
               | onislandtime wrote:
               | Hey, I checked your Reddit thread [1] and I see a good
               | discussion with useful suggestions. I don't see "anything
               | but hate" at all. There are pros and cons to using
               | frameworks. True, many people seem to prefer to use
               | smaller libraries. I personally don't like magic because
               | sooner or later I lose track of what's going on and need
               | to start guessing. With direct code I can understand
               | faster without having to read docs and layers of source
               | code. It's all about finding the right balance of
               | abstractions.
               | 
               | 1 - https://www.reddit.com/r/golang/comments/1anmoqg/what
               | _go_lib...
        
               | pepelotas wrote:
               | I liked gomega and ginkgo when I worked with it. But by
               | virtue of running tests serially, the race detection
               | becomes useless during testing, and I think it's a must
               | have. Has it changed?
        
               | joshlemer wrote:
               | And since it isn't a "framework" but rather just a wired
               | up collection of libraries, it would be pretty simple and
               | even a good learning process to change out the couple of
               | libraries one doesn't like (say, in case they prefer not
               | to use ent, and backlite).
        
           | DarkCrusader2 wrote:
           | I had this exact same experience with Go. I picked up .Net
           | (and Asp.Net for web stuff) on linux recently and found it to
           | be much more easier to get started batteries included than
           | Go. Don't need external libraries for any of the things you
           | mentioned (ORM, logging, metrics, DI etc.).
           | 
           | Razor pages are very interesting as well. I haven't used them
           | enough to have a solid opinion yet but I really liked them
           | for quick server rendered pages.
        
           | mattgreenrocks wrote:
           | About 50% of the time learning a new language I find that the
           | consensus framework/library choice is not quite to my taste.
           | It isn't that it's bad, it just often feels like one thing
           | went viral and then ends up boxed in by their success such
           | that people double down/put up with it rather than evolve it
           | further.
           | 
           | Point being you're probably going to spend those first five
           | days evaluating the options. The "community" doesn't know
           | your taste or your needs. You have no idea what their goals
           | are, or what the average skill level is. All of those things
           | can make a big difference in selecting tech to build atop of.
        
           | tptacek wrote:
           | 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 tests (without an assertion library), &c.
           | 
           | I'm not saying you need to stay there, but if your project
           | environment feels like Rails or Flask or whatever in your
           | first month or two, you may have done something wrong.
        
             | ljm wrote:
             | 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.
        
             | Attummm wrote:
             | I completely agree with the comment, except for the Flask
             | example. Django would be a better example.
             | 
             | Both Flask and Golang's http package have simplicity and
             | minimalism as their philosophy. Of course, most mature
             | projects will eventually diverge from that. But both can
             | start out as a single file with just a few lines of code.
        
           | jrockway wrote:
           | 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.
        
         | aczerepinski wrote:
         | It's why I moved my personal site from Phoenix to Go and it has
         | proven to he a great choice. I have zero dependencies so they
         | never go out of date.
        
         | ocdtrekkie wrote:
         | This used to be true of PHP as well, though them finally
         | picking off the hairy bits of bad assumptions has eroded that a
         | fair bit. For a long time you didn't usually need to concern
         | yourself what version of PHP 4-5 or so what version you were
         | running on.
        
         | almatabata wrote:
         | > 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.
        
         | arp242 wrote:
         | 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.
        
       | codegeek wrote:
       | What I love about Go is its simplicity and no framework
       | dependency. Go is popular because it has no dominating framework.
       | Nothing wrong with frameworks when it fits the use case but I
       | feel that we have become over dependent on framework and Go
       | brings that freshness about just using standard libraries to
       | create something decent with some decent battle tested 3rd party
       | libraries.
       | 
       | I personally love "library over framework" mindset and I found Go
       | to do that best.
       | 
       | Also, whether you want to build a web app or cli tool, Go wins
       | there (for me at least). And I work a lot with PHP and .NET as
       | well and love all 3 overall.
       | 
       | Not to mention how easy was it for someone like me who never
       | wrote Go before to get up and running with it quickly. Oh did I
       | mention that I personally love the explicit error handling which
       | gets a lot of hate (Never understood why). I can do if err != nil
       | all day.
       | 
       | A big Go fan.
        
         | jeffreyrogers wrote:
         | I like Go for this reason as well. In Python I found the Flask
         | framework to be suitably unobtrusive enough to be nice to use
         | (never liked Django), but deploying python is a hassle. Go is
         | much better in that area. The error handling never bothered me
         | either.
         | 
         | I think if Go shipped better support for auth/sessions in the
         | standard library more people would use it. Having to write that
         | code yourself (actually not very hard, but intimidating if
         | you've never done it before) deters people and ironically the
         | ease of creating Go packages makes it unclear which you should
         | use if you're not going to implement it yourself.
        
           | atomicnumber3 wrote:
           | My main gripe about go is that it's decent for the middle and
           | late stages and really really bad to start with. You'll spend
           | way too much time rewriting stuff you literally get for free
           | by running "rails new" or "bundle add devise"
        
             | vasilzhigilei wrote:
             | I love using Go for personal projects, but I keep finding
             | myself recreating the same redis-based session storage
             | logic, authentication, admin vs public routes, etc. Really
             | does burn time in the beginning, even though it's fun to
             | write the code.
        
               | tizzy wrote:
               | There is definitely space for an opinionated set of
               | libraries and boiler plate code for golang projects like
               | this.
               | 
               | Having said that, I'd bet that the go community consensus
               | is that you build one out yourself and reuse it. So most
               | times I end up copy and pasting the same logic rather
               | than recreating.
        
               | legorobot wrote:
               | 100% this. I have a set of commonly-used code in a
               | repository we use at work. AuthN/AuthZ, code specific to
               | our infrastructure/architecture, common http middlewares,
               | error types, DB wrapper, API clients, OpenAPI Server
               | generation, etc.
               | 
               | However, my personal projects have a different set of
               | code I reuse (more CLI- and tool-heavy focus), and I'm
               | sure other environments would have an entirely different
               | set of reused code.
               | 
               | On the opinionated library side of things, I did follow
               | LiveBud for a while, and Go-Micro but haven't really sat
               | well with the experiences from those, given how they lock
               | you in to different aspects of your stack.
        
           | codegeek wrote:
           | Some great points about the downsides of Go. Btw I was a
           | Flask junkie in early days.
        
           | leetrout wrote:
           | I am a Django apologist because I grew up with Django. So
           | with that being said, I'm not out to convert you but I am
           | genuinely curious what you don't like about it. Promise I
           | won't refute anything I just like to try to understand where
           | it turned off folks.
           | 
           | I don't like flask because it seems just easy enough to be
           | really productive in the beginning but you eventually need
           | most of the things Django gives you. So I would rather pick
           | up Django Rest Framework or Django Ninja than Flask or Fast
           | API. In those cases I jump straight to Go and use it instead
           | because the same library decisions on the Go side give me a
           | lot more lift on the operations end (easy to deploy,
           | predictable performance into thousands of requests per second
           | if built correctly).
        
             | jpc0 wrote:
             | I have to learn an entite framework and if I want to stray
             | away from what it wants the magic makes it hard.
             | 
             | For one, I so migrations with raw SQL onto the server, I
             | just don't trust it any other way and I dislike ORMs, I
             | even dislike query builders.
             | 
             | But for a big framework like Django you can't remove those
             | batteries easily and you have already strayed away from the
             | narrow paved road.
             | 
             | If I'm spinning up an API endpoint for my existing stack,
             | I'm picking flask ( well no I'm picking go because WSGI is
             | a pain in the... to deploy ) purely because I don't need
             | auth + rate limiting + an orm and all that. I need
             | endpoints exposed to do what I need, literally the rest is
             | already handled by my API gateway and it will be tied into
             | our existing management dashboard.
             | 
             | Django may be great to spin up a quick project but I found
             | I needed to stary for the paved road pretty quickly so I
             | rather picked a different tool...
             | 
             | This doesn't apply to everybody either, for aome Django is
             | the correct solution.
        
             | jeffreyrogers wrote:
             | It's opinionated in a way I dislike. I don't actually have
             | anything against opinionated software--tailwind is very
             | opinionated about how you should write CSS but I like it
             | because it matches up with how my mind works. But I find
             | Django very jarring. I can't point to a specific thing
             | about Django, it's more that if I were to design a
             | framework from scratch it would look nothing like Django,
             | so I experience a lot of friction trying to shape my ideas
             | about how to build an application into Django's way of
             | doing it. I have the same problem with Rails as well.
             | 
             | I agree with you that Django provides most things that an
             | application will eventually need, and if I were managing a
             | team that was starting a project from scratch I think
             | Django would be a reasonable choice, but aesthetically
             | something about it irritates me.
        
           | kolja005 wrote:
           | I'm curious in what sense you find Python difficult to
           | deploy? My company has tons of Python APIs internally and we
           | never have much trouble with them. They are all pretty
           | lightly used services so it it something about doing it on a
           | larger scale?
        
             | javcasas wrote:
             | There is a world of difference between having to install
             | python, libraries (some of them may require C-based libs
             | and compiling, therefore also install gcc), then configure
             | wsgi, hope it doesn't clash with other python versions or
             | have docker and containers... or just generating a fat
             | binary in go.
        
           | kaba0 wrote:
           | > (actually not very hard, but intimidating if you've never
           | done it before)
           | 
           | These stuff are never really hard, but you _will_ make
           | countless vulnerabilities that way. The most important job of
           | a good framework is cutting down significantly on the
           | possible to get wrong use cases, exposing you to already safe
           | APIs.
        
       | srameshc wrote:
       | Good to see author's mention about routing. I am mentally stuck
       | with mux for a long time and didn't pay attention to the new
       | release features. Happy that I always find things like these on
       | HN.
        
         | JodieBenitez wrote:
         | Nice new feature, would actually make me want to use Go without
         | Gin.
        
           | leetrout wrote:
           | I am over Gin and have been for years yet everyone keeps
           | using it because it has inertia. The docs are garbage.
           | 
           | Big fan of Echo and it has much better docs.
           | 
           | https://echo.labstack.com/
        
             | xerox13ster wrote:
             | I had to move from Gin to echo for my personal site, the
             | routing in Gin was refusing to serve static resources at
             | the root path without some headache.
        
             | JodieBenitez wrote:
             | Thanks for the suggestion, will give it a try. I'm more
             | familiar with Python than Go. I know my way around the
             | Python ecosystem and can make informed decisions about
             | which tool to use. Not so much with Go, so I appreciate
             | your advice.
        
       | physicles wrote:
       | GOMEMLIMIT has really cut down on the amount of time I've had to
       | spend worrying about the GC. I'd recommend it. Plus, if you're
       | using kubernetes or docker, you can automatically set it to the
       | orchestrator-managed memory limit using something like
       | https://github.com/KimMachineGun/automemlimit -- no need to add
       | any manual config at all.
        
         | nickzelei wrote:
         | Oh this is a good find. Thank you for sharing that link!
        
         | arccy wrote:
         | https://pkg.go.dev/go.uber.org/automaxprocs is another useful
         | one if you set CPU limits
        
       | yegle wrote:
       | It's sad https://pkg.go.dev/embed was not mentioned in a post
       | about web development in Go :-)
       | 
       | Having a true single binary bundling your static resources is so
       | convenient.
        
         | okibry wrote:
         | Which time golang read file, build time or run time ?
        
           | catlifeonmars wrote:
           | Build time
        
           | nasretdinov wrote:
           | embed package allows to embed assets directly into the
           | binary, so the files are read once during build time and then
           | you can access them as e.g. a byte slice, a string, or a
           | special FS object that acts like an in-memory file system
        
           | estebarb wrote:
           | Build time. It literally embeeds the file in the binary.
        
         | dullcrisp wrote:
         | It is mentioned now.
        
       | gwd wrote:
       | > 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:
       | 
       | https://gitlab.com/martyros/sqlutil/-/blob/master/txutil/txu...
       | 
       | That loop function should really have a Context so it can be
       | cancelled; that's future work. But the idea stands -- it should
       | be considered normal for transactions to fail, so you should
       | always have a retry loop around them.
        
         | returningfory2 wrote:
         | I don't think this controversial. Retrying failed transactions
         | is a common strategy.
        
           | gwd wrote:
           | You're the first person I've heard say so. When I was
           | learning DB stuff, there were loads of examples of things
           | that looked at the error from a transaction. Not a single one
           | of them then _retried the transaction_ as a result.
           | 
           | The OP's comment is a symptom of this -- they did some writes
           | or some transactions and were getting failures, which means
           | they weren't retrying their transactions. And then when they
           | searched to solve the problem, the advice they received
           | wasn't "oh, you should be retrying your transactions" --
           | rather, it was some complicated technical thing to avoid the
           | problem by preventing concurrent writes.
        
             | returningfory2 wrote:
             | Ah, interesting. Maybe my experience has been unusual then.
             | 
             | I agree with you the retrying transactions is relatively
             | simple and powerful.
        
             | bornfreddy wrote:
             | I'm in the opposite camp. Transactions can fail, however
             | retrying them is not the solution. It hides the symptom
             | (which is not a problem with proper monitoring), but more
             | importantly, it can lead to overwhelming the db server.
             | Sometimes failure happens because of the load, in which
             | case retrying the query is counterproductive. And even in
             | cases where retrying would be the correct approach, it is
             | the responsibility of the app logic, not of the db
             | connection layer, to retry the query. Imho of course. :)
        
         | rad_gruchalski wrote:
         | Wouldn't you need two contexts? One for retry cancellation, one
         | for underlying resources to be passed on to?
        
         | tedunangst wrote:
         | You'll just end up looping until your retry limit is reached.
         | SQLite just isn't very good at upgrading read locks to write
         | locks, so the appropriate fix really is to prevent that from
         | happening.
        
         | krackers wrote:
         | 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?
        
           | arp242 wrote:
           | _journal_mode=wal&_busy_timeout=200 seems to work well
           | enough.
        
         | Thaxll wrote:
         | You should never do blind retries in an infinite for loop,
         | ideally it should be a generic retry function ( bounded ) that
         | type check the error.
        
           | gwd wrote:
           | Yes, that's exactly what the linked code does: Calls your
           | function, and if it returns an error, check through the
           | wrapped errors to see if it's one of the SQLite errors which
           | should be retried. If it is, try the transaction again; if
           | not, pass the error up.
        
         | whizzter wrote:
         | Transactions are hard, and in reality there's a shit-ton of
         | things people do that has no right to be close to a transaction
         | (but still are), and transactions were a good imperative kludge
         | at the time that has just warped into a monster that people
         | kinda accept over the years.
         | 
         | A loop is a bad construct imho, something I like far better is
         | the Mnesia approach that simply decides that transactional
         | updates are self-contained functional blocks and the database
         | manages the transactional issues (yes, this eschews the regular
         | SQL interfaces and Db-application separation but could probably
         | be emulated to a certain degree).
         | 
         | https://www.erlang.org/doc/apps/mnesia/mnesia_chap4.html
        
         | marcosdumay wrote:
         | You shouldn't blindly retry things that fail as a default, and
         | you should really not default into making the decision of what
         | to do on a server that is just on the middle between the actual
         | user and the database.
         | 
         | Handling errors on the middle is a dangerous optimization.
        
       | imiric wrote:
       | 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 ever
       | want to do something slightly sophisticated, you'll have to
       | fallback to the manual approach. It's partly understandable,
       | though. It cannot realistically support every feature of every
       | DBMS, and it's explicitly not an ORM. But I still decided to
       | stick to the manual approach for everything, instead of wondering
       | whether something is or isn't supported by sqlc.
       | 
       | One tip/gotcha I recently ran into: if you run Go within
       | containers, you should set GOMAXPROCS appropriately to avoid CPU
       | throttling. Good explanation here[6], and solution here[7].
       | 
       | [1]: https://github.com/sqlc-dev/sqlc/issues/
       | 
       | [2]: https://github.com/sqlc-dev/sqlc/issues/3414
       | 
       | [3]: https://github.com/sqlc-dev/sqlc/issues/3394
       | 
       | [4]: https://github.com/sqlc-dev/sqlc/issues/3128
       | 
       | [5]: https://github.com/sqlc-dev/sqlc/issues/2760
       | 
       | [6]: https://kanishk.io/posts/cpu-throttling-in-containerized-
       | go-...
       | 
       | [7]: https://github.com/uber-go/automaxprocs
        
         | bornfreddy wrote:
         | 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.
        
         | 0x_rs wrote:
         | 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/
        
           | CBarkleyU wrote:
           | Unfortunately it relies on CGO for SQLite, which is a bummer
        
             | ncruces wrote:
             | Yeah, it'd be much nicer if libraries were designed to be
             | driver agnostic, like redka which supports 4 different
             | SQLite drivers:
             | 
             | https://github.com/nalgeon/redka/tree/main/example
        
       | rmac wrote:
       | 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 ?
        
         | coffeeindex wrote:
         | 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.
        
           | NAHWheatCracker wrote:
           | My experience with go build ./... is that it compiles
           | everything but it doesn't make the binaries.
           | 
           | > When compiling multiple packages or a single non-main
           | package, build compiles the packages but discards the
           | resulting object, serving only as a check that the packages
           | can be built.
           | 
           | From https://pkg.go.dev/cmd/go#hdr-
           | Compile_packages_and_dependenc...
           | 
           | A bit annoying when you want to build a bunch of executables,
           | but it's not something I need often and it's easy to script.
        
             | arccy wrote:
             | go build -o some/dir/ ./...
             | 
             | will actually output the binaries
        
               | NAHWheatCracker wrote:
               | Sick, I couldn't figure it out when I needed it so I just
               | manually created a 20 line script to cd into each
               | directory and go build.
        
       | trustno2 wrote:
       | 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
        
         | arp242 wrote:
         | 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?
        
           | kbolino wrote:
           | I don't know what issues others have had with it, but for me
           | one notable thing is that html/template strips all comments
           | out. This is by design, but it's not documented anywhere.
           | I've proposed making this configurable, but my proposal has
           | gotten no traction so far.
        
         | emmanueloga_ wrote:
         | Templ [1] is great!
         | 
         | Another go mod that helps a lot when massaging JSON (something
         | most web servers end up doing sooner or later) is GJSON [2].
         | 
         | --
         | 
         | 1: https://github.com/a-h/templ
         | 
         | 2: https://github.com/tidwall/gjson
        
         | sethammons wrote:
         | I am just trying Templ. I like what I am seeing for the most
         | part. There are some tooling ergonomics to work out. Lots of
         | "suddenly the editor things everything is an error and nothing
         | will autoimport or format" back to mostly working. Click to
         | definition goes to the autogenerated code instead of the templ
         | file. Couple things like that. But soooooooooo much better to
         | deal with code gen than html/template. That thing is a pita
        
       | kristianp wrote:
       | Does she (or anyone else here) use net/http's built in https
       | support? Seems implied by saying the built-in web server is used
       | in production.
        
         | eliben wrote:
         | Yes, all the time! The built-in net/http has great TLS support
         | 
         | https://eli.thegreenplace.net/2021/go-https-servers-with-tls...
        
       | ncruces wrote:
       | If you decide to use SQLite with one (single thread) writer pool
       | and an other reader pool, this may help:
       | https://github.com/bxcodec/dbresolver
       | 
       |  _Also sometimes if I have two tables where I know I'll never
       | need to do a JOIN between them, I'll just put them in separate
       | databases so that I can connect to them independently._
       | 
       | If this data belongs together and you're just doing this to
       | improve concurrency, this may be a case where BEGIN CONCURRENT
       | helps: https://sqlite.org/src/doc/begin-
       | concurrent/doc/begin_concur...
       | 
       | If you want to experiment with BEGIN CONCURRENT in Go you could
       | do worse than try my SQLite driver:
       | https://github.com/ncruces/go-sqlite3
       | 
       | Import this package to get the version with BEGIN CONCURRENT:
       | https://github.com/ncruces/go-sqlite3/tree/main/embed/bcw2
        
       ___________________________________________________________________
       (page generated 2024-09-29 23:00 UTC)