15 ms·
How to start a Go project in 2023
- athorax 3y agoThe article mentions GOW[0] for a file watcher. If anyone is looking for a non-go specific one, I've really enjoyed reflex[1]. Makes it super easy to reload different parts of a project based on what type of file has changed. [0]https://github.com/mitranim/gow https://github.com/mitranim/gow [1]https://github.com/cespare/reflex https://github.com/cespare/reflex
- synergy20 3y agohow about watchman? I use that one. https://manpages.ubuntu.com/manpages/jammy/man1/watchman.1.html https://manpages.ubuntu.com/manpages/jammy/man1/watchman.1.h...
- leetrout 3y agoMentioned in reflex's competition section I am a huge fan of entr https://github.com/eradman/entr https://github.com/eradman/entr
- jweir 3y agoSince we are mentioning these, I use entr # Makefile test: `find * -name "*.go" | entr bash -c "clear; go test ./..."` https://eradman.com/entrproject/ https://eradman.com/entrproject/
- puika 3y agoJust to add to the list there is also https://github.com/cosmtrek/air https://github.com/cosmtrek/air
- agotterer 3y agoI’ve been very happy with Air - https://github.com/cosmtrek/air https://github.com/cosmtrek/air
- jzelinskie 3y agoThings I can't live without in a new Go project in no particular order: - https://github.com/golangci/golangci-lint https://github.com/golangci/golangci-lint - meta-linter - https://goreleaser.com https://goreleaser.com - automate release workflows - https://magefile.org https://magefile.org - build tool that can version your tools - https://godoc.org/github.com/ory/dockertest/v3 https://godoc.org/github.com/ory/dockertest/v3 - run containers for e2e testing - https://github.com/ecordell/optgen https://github.com/ecordell/optgen - generate functional options - https://golang.org/x/tools/cmd/stringer https://golang.org/x/tools/cmd/stringer - generate String() - https://mvdan.cc/gofumpt https://mvdan.cc/gofumpt - stricter gofmt - https://github.com/stretchr/testify https://github.com/stretchr/testify - test assertion library - https://github.com/rs/zerolog https://github.com/rs/zerolog - logging - https://github.com/spf13/cobra https://github.com/spf13/cobra - CLI framework FWIW, I just lifted all the tools we use for https://github.com/authzed/spicedb https://github.com/authzed/spicedb We've also written some custom linters that might be useful for other folks: https://github.com/authzed/spicedb/tree/main/tools/analyzers https://github.com/authzed/spicedb/tree/main/tools/analyzers
- etxm 3y agoYou’ve gotta check out Charm’s tools for CLI/TUI dev. They are doing some great work. https://charm.sh/ https://charm.sh/
- tester457 3y agoCharm tools I can't live without: - https://github.com/charmbracelet/wish https://github.com/charmbracelet/wish - Golang SSH server that makes building SSH apps easy - https://github.com/charmbracelet/vhs https://github.com/charmbracelet/vhs - terminal GIF demos - https://github.com/charmbracelet/log https://github.com/charmbracelet/log - minimal and colorful go logs - https://github.com/charmbracelet/gum https://github.com/charmbracelet/gum - leverage charm's bubbles to write useful TUI shell scripts in any language
- omneity 3y agoAre there boilerplates that include things like this? (I’m coming from the JS/TS world)
- cyri 3y agowell written post! one minor thing: I've skipped using build tags for integration tests because those tests will be out of sync one day with your main code, even with Goland (?). Instead I use the usual test and check if an environment variable is set, if not, then t.Skipf("env var %q not set, skipping integration test",envVarName) or you can use an additional CLI flag, e.g. in `feature_test.go` write func init() { flagIntegration := flag.Bool("test.integration",false,"run int tests") } then $ go test -v -test.integration
- maerF0x0 3y ago> integration tests because those tests will be out of sync one day with your main code What do you mean here? What would be out of sync, and what would happen if it were?
- Crowberry 3y agoI usually make use of the long and short testmodes that are supported https://stackoverflow.com/questions/55180613/how-do-i-write-test-in-go-that-make-use-of-the-short-flag-and-can-it-be-combine https://stackoverflow.com/questions/55180613/how-do-i-write-... I used to use buildflags before this, but my linter ignored those files so they were hard to maintain
- puika 3y agoadditionally, if it's an integration test, you may want to always run with `-count=1` at least. e.g. if you use a DB, you certainly want to not skip any cached tests when the schema changes, etc.
- kardianos 3y agoPackage search: https://pkg.go.dev/ https://pkg.go.dev/
- maerF0x0 3y agoI'd add "What's the best web framework?" and answer it with "No." (Go comes batteries included)
- rollulus 3y agoThat’s quite true, although for routing / muxing I do tend to use a third party one. The numerous Go web frameworks are solely created for the glory of the authors.
- LVB 3y agoA better answer would be some recommendations for component pieces. e.g., I will need most of the essential things in https://github.com/go-chi/chi https://github.com/go-chi/chi, so why bother rolling a version myself? The same goes for things like sqlx. I'm averse to leaning on a "framework," but do find good value in targeted libraries.
- liampulles 3y agoAnd in general, one does not need frameworks in Go to the same degree as say Java or C# - it is an easier language to build things from scratch with I think.
- za3faran 3y agoHaving worked on a large golang project that did not use any "frameworks", it gets clumsy quickly. There's nothing special in golang that makes it not need a framework. We ended up moving the project to a DI framework with an ORM-ish library since things got out of hand.
- liampulles 3y agoMy experience at work is different, but I guess every project has its own needs
- alex_lav 3y agoThis is just generally bad advice. The code that gets written as every single project that "doesn't need" web frameworks is just a worse, less secure, more error prone version of the code that comes in every well-supported web framework.
- rollulus 3y agoPretty good article. One comment: it recommends zerolog for logging, but recently slog [1] has started to become part of the standard lib. I guess it’s the future. [1]: https://pkg.go.dev/golang.org/x/exp/slog https://pkg.go.dev/golang.org/x/exp/slog
- arp242 3y agoI used slog for a project a few months ago; then I stopped working on it and continued on it a few weeks ago and there were all sorts of incompatible changes. That's completely fair; it's still in development so this isn't a complaint! But just saying, at this point you need to be prepared to have to deal with that.
- xh-dude 3y agoFWIW: slog has been pretty stable for a month or two, and should be officially standard library in go1.21 There was a last round of changes mostly revisiting use of contexts a few months ago - hats off to jba for taking a lot of time to work out the best fit
- wizhi 3y agoWhere do you keep up to date on what will be included in future releases?
- roesl027 3y agoA few places I look: - https://dev.golang.org/release#Go1.21 https://dev.golang.org/release#Go1.21 - might be the same info as https://github.com/golang/go/milestone/279 https://github.com/golang/go/milestone/279 in a different form and here is a link to the draft release notes https://tip.golang.org/doc/go1.21 https://tip.golang.org/doc/go1.21
- liampulles 3y agoI use zerolog at work - I can vouch that it does the job just fine.
- bitwize 3y ago[flagged]
- steveklabnik 3y agoPlease don't do this.
- jasonthorsness 3y agoI see the note in the article around using -ldflags="-s -w" - is there any other useful tool for binary size analysis/reduction? I was surprised when my binary size doubled when incorporating the K8s client package to get a secret; just using the HTTP secrets API manually without referencing the client package shrank the size by many MB. It would be nice to find similar opportunities for size reduction that aren’t as obvious.
- typical182 3y agogoda[0] is excellent. You do do things like: # show the impact of cutting any package goda cut ./...:all which prints a sorted ASCII table with stats like 'size:4.4MB loc:134171' for each package, which is an estimate the savings you'd get if you eliminated that package from your binary. That is a great way to see what is unexpectedly large compared to its value. goda has a bunch of other capabilities around dependency analysis, and was written by long-time Go contributor Egon Elbre. The examples in the README are the best way to get started after 'go install github.com/loov/goda@latest'. [0] https://github.com/loov/goda https://github.com/loov/goda
- liampulles 3y agoThe go k8s packages are pretty bloated - this may also just be a niche case. If you are looking to get secrets with hot reloading, you might also consider mounting a file or setting env vars and coupling it with this reloading operator: https://github.com/stakater/Reloader https://github.com/stakater/Reloader
- alecthomas 3y agogo-binsize-treemap[1] is the best tool for this by a large margin. I came across it because of the exact same reason as you did actually, k8s client bloating my binary massively. [1] https://github.com/nikolaydubina/go-binsize-treemap https://github.com/nikolaydubina/go-binsize-treemap
- nologic01 3y agoLooks like a good resource for go beginners. Would there something similar for a next, second, step that focuses on go concurrency aspects? Go (and erlang/elixir) as touted as concurrency-ready platforms and good overviews of setups, tools and best practices might help more people benefit.
- lima 3y agoHow to start a new Go project: go mod init mymodule Go's default toolchain is fine, everything else is optional. Some questionable advice in the article: - Vendoring dependencies using "go mod vendor" is not a good default workflow - it bloats the repo, the checked in code is impossible to review, and is generally a pain to keep up to date. Don't, unless you really have to. - There's no point in stripping a binary or even using UPX on it unless you're targeting extremely low memory environments (in which case Go is the wrong tool anyways), all it'll do it make it harder to debug.
- up2isomorphism 3y ago“Not keeping up to date “ is one of the mostly important features nowadays, in fact.
- vardump 3y agoUPX only means smaller files on the disk, but it comes with a cost: it tends to increase memory requirements, because the binary on the disk cannot be mapped to memory anymore. Unless it's uncompressed somewhere in the filesystem. Worse, if you run multiple instances of the same binary, none of them can be shared. A bit simplified, without UPX, 100 processes of 100 MB binaries requires only 100 MB RAM for the code, but with UPX 10 GB. Edit: In reality, likely only a fraction of that 100 MB needs actually to be mapped into memory, so without UPX true memory consumption is even less than 100 MB.
- cced 3y agoCan you expand on this a bit? I use upx at work to ship binaries. Are you saying these binaries have different memory usage upx’d than they do otherwise?
- themerone 3y agoEvery instance of a program will use an amount of ram equal to the uncompressed size. If the application is uncompressed, the uncompressed executable will be loaded into ram 1 time and be reused by every instance of the application.
- shellac 3y ago[flagged]
- tptacek 3y agoI don't know, it's a complicated question, and it has nothing to do with the article and asks for a big language fight.
- icholy 3y agoGo has better dependency management than most modern languages.
- kortex 3y agoWhat's "most modern languages"? Go is better than Python's native tooling (only Poetry and other similar 3rd party tools compare). Javascript I find unruly and fragmented. "Modern" C++ is still a nightmare. Java I haven't touched but I don't exactly hear rave reviews or angry rants about, so I expect it's middling. Rust, scala, and haskell are definitely better experiences, but they are definitely in the minority in terms of industry usage. Go is not "quite bad", in fact far from it. I'd say it's better than average.
- shellac 3y ago> What's "most modern languages"? Go is better than Python's native tooling (only Poetry and other similar 3rd party tools compare). Javascript I find unruly and fragmented. Exactly the scale I had in mind, thanks. When I saw 'go get <package>' rather than dependencies added to the equivalent of a Gemfile / cargo / pom file it had concerns.
- kortex 3y agoThere's nothing stopping you from adding to go.mod though, you just have to update the sumfile, no different than using pyproject.toml directly vs adding with CLI.
- bborud 3y agoWhat are you comparing to and what do you think the shortfalls are? What is a "modern" language?
- tptacek 3y agoGo is pretty mainstream now, so if your editor is mainstream too, just keep using it and add its Go support; you don't need to pick a Go-optimized editor. The basic thing I think you really want is something like `goimports` (which you can just install), which automatically manages your imports for you and takes out 80-90% of the pain of Go's library usage policy.
- cratermoon 3y agoNote that statically linked go binaries work in a docker image from scratch. This can be created with a multi-stage build where the builder image uses whatever OS you prefer, with any required packages. A build line such as RUN CGO_ENABLED=0 go build -o mybin -ldflags '-extldflags "-static"' -tags timetzdata And the second stage like FROM scratch COPY --from=app-builder mybin mybin ENTRYPOINT ["/mybin"] The builder can create users and groups, and the final image can import necessary certs like so: COPY --from=alpine:latest /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
- deleted 3y ago[deleted]
- sureglymop 3y agoGenuine question.. I'll often see Golang pretty heavily criticized here on hacker news. Either that or people say it's a boring language and not worth learning when there is something more interesting (usually referring to Rust or Zig). Why does it have such a bad image? Personally i like it as an alternative for python because: 1. It can build binaries that just work for most architectures quickly. 2. It has nice c-like syntax without some of the headaches. 3. It seems to be really nice for creating apis or backends, especially for web projects. Lately i use it as an alternative to php, to build MPAs which are enhanced with htmx. 4. It seems very beginner friendly and easy to start with and has a non-gatekeepy community. There are also some things i don't like so much such as: 1. Goroutines and other go specific stuff 2. The dependency system requiring full import paths with urls. 3. The strictness about syntax etc. The fact that saving a file with an unused import will remove it in the ide. But it overall seems much nicer than running node/js or python on the server side, no?
- 0zemp2c 3y agoHN loves playing "obligatory contrarian" so often commenters will go to lengths to find faults there is nothing wrong with Go; it delivers on its promise, you don't need to be a genius to use it, has good community support, and you can get access to a large and decent job market Rust is a great tool but isn't as purpose-suited to network services as Go Zig is even less purpose-suited to writing network services and won't be at Go's level of maturity for years, if ever If a backend dev could only know one language in 2023, it would be hard to go wrong with Go
- shakow 3y ago> but isn't as purpose-suited to network services as Go Why?
- sapiogram 3y ago+1. In terms of development speed, Node + Axios is lightyears ahead. It's like 5 lines of code to send a JSON payload via http, vs 15+ in Go. The Javascript version is much likely to be correct as well, since it doesn't let you forget to check any of the three errors, or forget to check the http status of the response.
- dhagz 3y agoOne thing for profiling HTTP services specifically, you can attach handlers for pprof data easily [0]. I usually only mount the routes if I've set a flag for it, usually something to indicate I want to run in debug mode. This does everything "for free", i.e. it starts profiling memory and CPU and then exposes the data on routes for you to visualize in the browser. [0]: https://pkg.go.dev/net/http/pprof https://pkg.go.dev/net/http/pprof
- vaunt_dev 3y agoWe create a Generic HTTP Handlers enable developers to create functions, methods, and data structures that can operate on any type, rather than being limited to a specific type. https://blog.vaunt.dev/generic-http-handlers https://blog.vaunt.dev/generic-http-handlers
- arriu 3y agoOne thing I wish there was better support for is live debugging and stepping through code.
- poo-yie 3y agoYou know about VS Code and GoLand?
- puika 3y agoI absolutely love the integration in VSCode with the official Go extension. I can debug a running web server with delve with minimal config. Same for tests. Just experiment with the options, there are quite a lot, and unfortunately some not very well documented like gopls ones, at least last time i checked.
- kortex 3y agoI see $GOPATH is no longer strictly needed, which is nice. But what's the deal with $GOROOT? I seem to always need it set but I don't know if that's just my workflow or force of habit.
- BarkMore 3y agoIt's either habbit or you are doing something out of the ordinary with your Go installation. The standard installation of Go has not required GOROOT for a very long time.
- typical182 3y agoPeople should essentially never set GOROOT. It's mostly a holdover. For example, Ian Lance Taylor on the core Go team wrote [0] somewhat recently: "It's a special purpose hook that is almost never needed". [0] https://groups.google.com/g/golang-nuts/c/qDhJbkE1QeY/m/JoV2bxWtBwAJ https://groups.google.com/g/golang-nuts/c/qDhJbkE1QeY/m/JoV2...
- liampulles 3y agoI use Makefiles for my projects, and right at the top I do: GOBIN := $(shell go env GOBIN) And then use that var where needed.
- revskill 3y agoWorking with Go is boring but productive. Go libraries are reliable, fast. It's more than enough to write good software.
- cpuguy83 3y ago"go mod init <stare at the terminal endlessly trying to decide on a name>". Minor improvement over "mkdir -p $GOPATH/src/path/in/vcs/remote/<stare at the terminal endlessly trying to decide on a name>" /s
- xarope 3y agoye olde two hard problems in CS, naming and cache invalidation (and off by one)
- SergeAx 3y ago> The solution is to upgrade [Go language] after a week or so I personally have a habit of updating only when the next patch version is out. It saved be countless hours of debugging and frustration.
- maxmcd 3y agoPlease don't use build tags for integration tests: https://peter.bourgon.org/blog/2021/04/02/dont-use-build-tags-for-integration-tests.html https://peter.bourgon.org/blog/2021/04/02/dont-use-build-tag... Along with the issues listed here you will run into issues with editors not building/linting your tests files because they have build tags that the editor is unaware of. You can also put the environment variable in a TestMain[1] to cover an entire package of integration tests: func TestMain(m *testing.M) { if os.Getenv("RUN_INTEGRATION_TESTS") == "" { fmt.Println("Skipping integration tests") return } os.Exit(m.Run()) } [1] https://pkg.go.dev/testing#hdr-Main https://pkg.go.dev/testing#hdr-Main
- eweise 3y agoLooks like more boilerplate to me.
- SPascareli13 3y agoI made this mistake in a project at work...never again.
- mparnisari 3y agoThe mistake of using build tags, or the mistake of not using them?
- SPascareli13 3y agoUsing them.
- Groxx 3y agoPersonally I like putting them in the tests, with t.Skip (frequently further in the code, in whatever sets up test dependencies that makes it an "integration" test, so it's automatically skipped). That way you can blend unit and integration in the same package.
- Scotch3297 3y agoWell, you can configure your editor to lint your test files with build tags and that's the end of the issue. At least on VSCode and Goland you can. I think it's way cleaner to have your integration tests with a build tag rather than this extra piece of code. If you don't have tests all over the place and you are moderately organized with your folder structure, there is no reason why build tags should represent a discoverability issue.
- syngrog66 3y agojust start writing some Golang. same as any other programming language for decades now. Really thats all you need to get started. OK: a text editor, the Golang toolchain and ideally a terminal/shell. Worry about other things if/when they come up, right in your face. Assume by default: YAGNI.
- hintymad 3y agoAny de-facto service framework in Go to recommend, something like Dropwizard but supports both gRPC and HTTP APIs? Such framework should also has ready-to-use integrations things like metrics, logging, tracing and etc. And God please don't just support Prometheus. A pulling-based `/metrics` is really not the best solution, at least not always.
- liampulles 3y agogo-micro is a well known one (though I've never used it): https://github.com/go-micro/go-micro https://github.com/go-micro/go-micro In my own experience coming from a Java background, I find Go much easier to build from scratch with since the control flow is so plain and the standard library API is simple and well designed - worth trying.
- deleted 3y ago[deleted]
- j3s 3y agoi don't like this post because it makes golang feel overwhelming when the stdlib + default tooling is plenty good for most use-cases. it's as if someone made a post called "how to go hiking in 2023" and spent 10 pages linking to gear on amazon. how should you actually start hiking? grab a water bottle, get outside, and hike. here is how you should _actually_ start a go project in 2023: $EDITOR main.go go run . everything else you should add as needed. don't overcomplicate things.
- opportune 3y agoYeah, for a basic Go service or tool I don’t think you usually need anything besides the standard lib. Maybe you will want to use a client library but most of the time it’s only thinly wrapping various http functionality. I work on some go binaries used at massive scale that have little/no dependencies.
- shepherdjerred 3y agoOn the other hand, the article contains information about things you are likely to need. This is the exact article I would want to present to someone new to the language. It isn't recommending every tool in existence (well, until you reach the very end) -- it's simply giving information about what you'll almost certainly need to know
- nirui 3y ago> the article contains information about things you are likely to need Then maybe write something on the specific topic in detail than bundling them into a How-To tutorial. A How-To tutorial is suppose to show "how to" do something correctly, it's a teach than showcase. I do understand that the author was writing this article with best intentions in their mind, but the resulting article is not a How-To, rather, it's a How-Do-I which is opinionated. I think when reading articles like this, it is important to remember that, sometimes, more is less. You import this many tools into your project, many of them are unnecessary and will not help you completing the project, now they've been download and installed, maybe they're even interfering with other tools. You look at them and starts to think "hey, make be I should learn to integrate and utilize them". Then you wasted an afternoon trying to utilize the tool, but by the evening you realized that in order to use the tool correctly, you must restructure your project. This is not how you can finish things, you know? If you want to write a new project, just `go mod init` it and write the code. And during the writing, if you found the need for some tools, just introduce those tools one by one to fulfill the need. Don't downloading tools or creating "project layouts" just because some tutorial said so.
- baby 3y agoI've left Golang for a while, then when I came back it felt a bit complicated to figure out how to get started. I feel rustup.rs, really got Rust to a much better spot than Golang in such a short amount of time.
- Patrickmi 3y agoCould you share some light on how Go became “a bit complicated” ?
- mparnisari 3y agoIf your code uses goroutines i recommend https://github.com/uber-go/goleak https://github.com/uber-go/goleak to detect leaks And then for GUID generation we use https://github.com/oklog/ulid https://github.com/oklog/ulid instead of https://github.com/google/uuid/ https://github.com/google/uuid/
- Daegalus 3y agoI would like to mention Magefile. We recently have been using it over makefiles and it has been amazing. Removes more non-go dependencies. You write your files in Go, and it all works really well. https://magefile.org https://magefile.org Between that, goreleaser, 2-stage dockerfiles, static binaries, etc. It all just works so well and only needs Go for most things. Recently for actual stuff we have been using Exho, Zerolog, and fairly common libraries for most tools.
- deleted 3y ago[deleted]
- metaltyphoon 3y agoDoes Go allow to load an in-process profiler like the CLR (dotnet)? It’s very useful for application monitoring, e.g NewRelic, DataDog.
- kylequest 3y agoCool to see that people still find "50 Shades of Go" useful :) If anybody has additional gotchas you want to share I'd love to add them!
- TurboHaskal 3y agoThis is how I start a Go project in 2023. mkdir new-repo vim new-repo/main.go I try to stick to the stdlib as much as possible, which goes surprisingly far.
- rusl1 3y agoI'm learning Go right now and these comments are really precious, so many useful respurces
- holografix 3y agoNo mention of govuln?!
- butterisgood 3y agoWould love to see this with Erlang/rebar3 or LFE or Gleam or Elixir…
- juggli 3y ago1. go mod init. 2. read&write the f*k source code. nothing else