[HN Gopher] How to start a Go project in 2023 ___________________________________________________________________ How to start a Go project in 2023 Author : taylorbuley Score : 262 points Date : 2023-05-23 16:31 UTC (6 hours ago) (HTM) web link (boyter.org) (TXT) w3m dump (boyter.org) | kortex wrote: | I 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. | typical182 wrote: | People 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/JoV2... | liampulles wrote: | I use Makefiles for my projects, and right at the top I do: | | GOBIN := $(shell go env GOBIN) | | And then use that var where needed. | BarkMore wrote: | It'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. | tptacek wrote: | Go 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 wrote: | Note 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/ | rollulus wrote: | Pretty 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 | arp242 wrote: | I 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 wrote: | FWIW: 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 | liampulles wrote: | I use zerolog at work - I can vouch that it does the job just | fine. | jzelinskie wrote: | Things I can't live without in a new Go project in no particular | order: | | - https://github.com/golangci/golangci-lint - meta-linter | | - https://goreleaser.com - automate release workflows | | - https://magefile.org - build tool that can version your tools | | - https://godoc.org/github.com/ory/dockertest/v3 - run containers | for e2e testing | | - https://github.com/ecordell/optgen - generate functional | options | | - https://golang.org/x/tools/cmd/stringer - generate String() | | - https://mvdan.cc/gofumpt - stricter gofmt | | - https://github.com/stretchr/testify - test assertion library | | - https://github.com/rs/zerolog - logging | | - https://github.com/spf13/cobra - CLI framework | | FWIW, I just lifted all the tools we use for | 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 | donatj wrote: | Cobra is just so... intense and complicated. It has it's place | but Google's Subcommands is enough for 99.9% of projects I've | worked on | | - https://github.com/google/subcommands | azemetre wrote: | hmm I recently just finish making a CLT with cobra and it | wasn't too bad. Granted it's extremely basic but I like it | for my use case (cloning all the repos in an org): | | https://github.com/shimman-dev/piscator | | What did you find complicated about it? What I struggle with | is creating man pages automatically, although I did just find | where in the repo this is explained. | | subcommands does look neat tho, I'll likely use it for | another tool I have in mind. | | One thing I did not realize is that cobra and | charmbracelet/bubbletea are not compatible. It may be my | inexperience in making CLTs vs TUIs but I was disappointed I | could use say the loading spinner from bubbles easily in my | tool (opted for briandowns/spinner instead). | icholy wrote: | I like https://github.com/urfave/cli | jacurtis wrote: | I've built many CLIs with Cobra and haven't found it all that | intense. I've built incredibly simple, single function CLIs | up to some incredibly advanced CLIs that the entire company | relies on daily. | | I like Cobra because it gives you a great place to start, | with tons of stuff "for free". Things like spellcheck on | commands like if you type "mycli statr", you might get a | response "mycli statr command not found. Did you mean mycli | start?". This is out of the box. I don't do a single thing to | create this functionality. Really nice help pages, automatic | --help flags with autodocumentation all comes for free, by | just running a simple init script to start the project. It | speeds up my ability to make a reliable CLI because I don't | need to worry about alot of the little things, I basically | just create the command I want, choose the flags, and then | start writing the actual code that performs the task and | don't have to write very much code to manage the tool. | | I usually organize my project so all the Cobra stuff is in | the main module. Then I write my own custom module that | contains the application code that I am building. It builds | great seperation between the two. The main module just has | cobra setup, flags, configuration, documentation, etc.. Then | for each command, all I do is call a function from my module, | where all the logic resides. | | This makes it easy for me to switch between a "Cobra" context | and my "Application" context depending on the module. It also | makes it portable. If i want to use a different CLI framework | or make this into a backend job, I can pull my module into a | different project and then call the functions from that other | project that reside in my module. The module is unaware of | Cobra entirely, but it performs all my logic. The cobra | module (the main module) contains only Cobra stuff and then | offloads all the logic to my application module. | | Cobra has all the power you could want from even the most | advanced CLIs (I think github's CLI and Kubectl, kubernetes | cli are both built on it for example). But you don't need to | use any of the advanced stuff if you don't want. It means | there is a lot of confidence to build a project in cobra and | if it grows you won't be limited, but it also abstracts the | complexity away when the project is simple. | | I don't have a dog in this fight, just a fan. It is a tool I | really appreciate. I will check out subcommands though, it | looks like a good project. Reminds me of "click" for python. | nvy wrote: | >spellcheck on commands | | I prefer to just type "fuck": | | https://github.com/nvbn/thefuck | andrenth wrote: | > - https://godoc.org/github.com/ory/dockertest/v3 - run | containers for e2e testing | | For this there is also the testcontainers project, which has | support for Go and other languages. | | https://golang.testcontainers.org/ | etxm wrote: | You've gotta check out Charm's tools for CLI/TUI dev. They are | doing some great work. | | https://charm.sh/ | tester457 wrote: | Charm tools I can't live without: | | - https://github.com/charmbracelet/wish - Golang SSH server | that makes building SSH apps easy | | - https://github.com/charmbracelet/vhs - terminal GIF demos | | - https://github.com/charmbracelet/log - minimal and colorful | go logs | | - https://github.com/charmbracelet/gum - leverage charm's | bubbles to write useful TUI shell scripts in any language | omneity wrote: | Are there boilerplates that include things like this? (I'm | coming from the JS/TS world) | emmelaich wrote: | Perhaps https://github.com/lacion/cookiecutter-golang ? | | Might be a little out of date. | cyri wrote: | well 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 | Crowberry wrote: | I usually make use of the long and short testmodes that are | supported 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 | maerF0x0 wrote: | > 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? | syngrog66 wrote: | just 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. | mparnisari wrote: | If your code uses goroutines i recommend https://github.com/uber- | go/goleak to detect leaks | | And then for GUID generation we use https://github.com/oklog/ulid | instead of https://github.com/google/uuid/ | [deleted] | bitwize wrote: | [flagged] | steveklabnik wrote: | Please don't do this. | kardianos wrote: | Package search: https://pkg.go.dev/ | maxmcd wrote: | Please don't use build tags for integration tests: | 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 | eweise wrote: | Looks like more boilerplate to me. | UGIForAll wrote: | which languages are the best | sureglymop wrote: | Genuine 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? | dboreham wrote: | It's just not a shiny squirrel thing in a tree, that's all. | opportune wrote: | Golang is IMO the best applications language. Most of my | criticisms of it would be that it makes some systemsy things | clunky, and because of garbage collection it just isn't ideal | for some systemsy stuff. | | I personally hate the empty interface and definition shadowing | of Go but that could be just me not "getting it". Fortunately | at work we don't use that too often | | I think most of the criticism is from people like me coming | from C++. I am continually baffled that people write web | backends in Python and Node at all, to me they seem so | inappropriate that criticizing them would be a waste of time. I | would consider Go to be much much better overall, and thus | worthy of actual criticism | tomcam wrote: | Don't worry about it. Your assessments are exactly correct. | | I'm not putting down any other development environments, but | everything you say is absolutely true in your circumstances | (mine too). | bitwize wrote: | Yeah, it's pretty much optimized for junior programmers to | write babby's first enterprise network service in. It's got a | lot of features junior programmers think are nice and easy to | work with, but as you mature as a developer its verbosity | becomes annoying and its shortcomings become apparent. | | Using Go as a PHP alternative is pretty much the use case most | aligned with its niche. So go nuts if you like doing that. But | stray too far from that use case and Go will start to provide | pain without adequate justification, especially when compared | against Zig, Rust, or even TypeScript. | avgcorrection wrote: | > Genuine question.. | | There have been about a hundred "why Go"/"why not Go" threads | on Hacker News already. | Patrickmi wrote: | It's simple when you have WhatsApp vs BlackBerry Messenger and | we know that WhatsApp wins, you begin to question yourself | what's making blackberry win even tho it's inferior, then | hearing their secret weapon "Simplicity" trying to mimic the | secret weapon but yet still wondering why isn't going as | expected, this is what is happening No matter how go improves | people will still talk about its past failures with present | failures, so you don't have to worry people will still use the | language and its competition | hombre_fatal wrote: | > But it overall seems much nicer than running node/js or | python on the server side, no? | | No, it's just trade-offs. | | I think you are making the same mistake by looking for | validation on HN that you're making some sort of Better Choice, | but you're just making a normal choice. You just don't yet have | the experience to see all the trade-offs nor how they compare | to, say, Node or Python. | | For example, there are various ways Node is "nicer" than Go on | the server. Just compare things like Promise.all or a | concurrency-limited Promise.map to Go's WaitGroups. | sureglymop wrote: | But I'm not really making a choice. I'm open to anything, i | don't want to restrict myself. I have and do use the things i | mentioned a lot (node/python). I was just curious what the | people have to say since i noticed this recently. I don't | really need the validation since I'll try out all available | options due to curiosity anyway. | liampulles wrote: | It is a boring, no-magic language on purpose. | | I think it appeals to cynical devs who have seen projects | misuse more powerful languages, and who don't want to debate | style guidelines or linter settings for any more than 5 | minutes. I count myself among them. | gadflyinyoureye wrote: | It's verbose. Errors everywhere. | | There are a lot of foot guns. nil slice? Fine. nil map? | Segfault. Loop variables with closures. The list goes on. | | Generics seemingly split the community. May be some libraries | won't get used because they picked the wrong side. | | It's surprisingly weak at modeling data. Union types would | really help out. | | The community is so anti-design that it's hard to play with | them. Most want to make a big ball of mud and call it agile. | When you point out simple patterns, they call you an Architect | Astronaut. Checkout r/golang. Also look out for people telling | you how dumb you are for wanting generics. | | In many cases it's a step backwards but it has the positives | you posted. That is often a reason to grin and bear it. | Eventually Stockholm Syndrome kicks in. | 0zemp2c wrote: | > Loop variables with closures | | indeed a brutal footgun but will be fixed soon | sapiogram wrote: | Have they actually agreed on how to fix this now? | typical182 wrote: | > Generics seemingly split the community. May be some | libraries won't get used because they picked the wrong side. | | I haven't really observed that at all. | | One thing that is going on is there hasn't been a massive | disruption while everyone stops to rewrite the world in | generics, and generics are not suddenly everywhere, which is | what some people had predicted would happen. I think part of | the reason is that in some cases another solution (closures | or interfaces or whatever) can be a better fit, and the | evolutionary approach to generics that Go took means you can | use generics in conjunction with non-generic libraries or | other pre-existing approaches without suffering from an | ecosystem split. | 0zemp2c wrote: | HN 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 wrote: | > but isn't as purpose-suited to network services as Go | | Why? | sapiogram wrote: | +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. | Daegalus wrote: | I 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 | | 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. | j3s wrote: | i 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 wrote: | Yeah, 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. | hintymad wrote: | Any 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 wrote: | go-micro is a well known one (though I've never used it): | 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. | vaunt_dev wrote: | We 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 | jasonthorsness wrote: | I 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 wrote: | goda[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 | liampulles wrote: | The 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 | dhagz wrote: | One 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 | nologic01 wrote: | Looks 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 wrote: | How 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. | latchkey wrote: | > There's no point in stripping a binary or even using UPX on | it unless you're targeting extremely low memory environments | | I really dislike absolutes like this. | | My target is 30,000+ servers and distributing a binary to all | of them is a lot easier when it is 3m than when it is 26m. | nemothekid wrote: | If the problem is distribution, what's wrong with gzip? All | the upsize of UPX and none of the downsides. If your | distribution method is http, then you don't even have to | write any code other than setting a Content-Encoding header. | latchkey wrote: | gzip doesn't make it small enough. | | 3mb is after `xz -z -9e`. | | But, if you start with something smaller, you generally get | something even smaller. | | I tried UPX, but ended up with just `-s -w` (and xz), | simply because UPX was taking too long to build the binary | in CI. | | More importantly though, I was responding to OP's absolute. | Thaxll wrote: | I don't really believe that, at the speed of nic it makes | pretty much 0 difference even on 30k servers. Shaving couple | of ms at worse few seconds vs modifing a binary, def not | worth it. | latchkey wrote: | The servers are not all on gige. Many are on 100mbit and | yes, that saturates the network when they are all updating. | I learned through trial and error. | | The updates are not pushed, they are pulled. Why? Because | the machines might be in some sort of rebooting state at | any point. So trying to first communicate with the machine | and timeouts from that, would just screw everything up. | | So, the machines check for an update on a somewhat random | schedule and then update if they need to. This means that a | lot of them updating at the same time would also saturate | the network. | | Smaller binaries matter. | hnlmorg wrote: | I'm curious why you've got servers on 100Mb. Last time I | ran a server on 100Mb was more than 20 years ago. I | remember the experience well because we needed AppleTalk | support which wasn't trivial on GbE (for reasons | unrelated to GbE -- but that's another topic entirely). | | What's your use case for having machines on 100Mb? Are | you using GbE hardware but dropping down to 100Mb, and if | not, where are you getting the hardware from? | | Sounds like you might work in a really interesting domain | :) | pdmccormick wrote: | Sounds like an interesting problem to have. Would | something peer-to-peer like BitTorrent work to spread the | load? Utilize more of the networks' bisectional | bandwidth, as opposed to just saturating a smaller number | of server uplinks. I recall reading many years ago that | Facebook did this (I think it was them?) | sethammons wrote: | I'm on the vendor bandwagon; always have been. I don't want a | github outage to dictate when I can build/deploy. Yes, that | happened. That is why we vendor :). | | Now you can set up a proxy server; however, I don't want to do | that. I'm pretty sure I have a few vendored packages that no | longer exist at their original import path. For code reviews, | we put off checking in the vendor path til the end if possible. | jasonwatkinspdx wrote: | I like vendoring in most languages as it means I can follow | all the code flow easily in my editor when debugging | something. | djbusby wrote: | I do all my vendor in a "cache-proxy" thing (for lots of | vendors). That box always runs, I just need upstream the | first time I get the package. Doesn't bloat my code, makes | sure package is available and makes audits of vendor stuff | easy. | attentive wrote: | also increases startup time | didip wrote: | There is a benefit to using "go mod vendor". Some corporate | environments lock down their CI/CD pipelines. By vendoring | everything, the CI/CD does not need to make external HTTP | calls. | 0zemp2c wrote: | vendoring is a bit of project smell, but for large teams it | removes the confusion of who has what version of a dependency | | unfortunately most teams don't schedule a periodic `go mod | tidy` so you just end up with ancient deps | | most people never read the code of the deps they pull in, so I | don't think vendoring provides any security assurances | dilyevsky wrote: | > it removes the confusion of who has what version of a | dependency | | go.mod/sum files already remove that confusion as it's their | intended purpose | icholy wrote: | That's not what `go mod tidy` does ... | Paul-Craft wrote: | I'd go way farther than "a bit of a project smell." I | literally cannot think of a single instance in which | vendoring a dependency for any reason other than, say, | caching it for CI so you don't have to worry that the | maintainer pulls a `left-pad` on you, has gone well. | | If the package has bugs, you're far better off either waiting | for upstream fixes, working around the bug in your | application code, or just switching to a different library. | That goes double if the library you're using is missing a | feature you need, even if it's scheduled for the next version | release. | | Unless you're prepared to maintain a full-on fork of the | dependency (and, if you do, _please_ make it public), | everything about vendoring for these reasons is 100% bad for | you for very little incremental benefit. It 's like the joke | about regular expressions ("You have a problem and think | 'I'll use regexes to solve it.' Now you have two problems"), | except it's not a joke, and it sucks way more. | | TL;DR: Vendoring to cache for CI/build servers, yes. Any | other reason, just don't; it's not worth the headaches. | ownagefool wrote: | If you work on code that introduces threat to life, you | might be prepared to own all the code, even if you don't | write it all from scratch. | pdmccormick wrote: | A Go vendoring pattern that I've found very useful is to use | two repositories, the first for the main "project" repository, | then a second "vendoring" repository that imports the first as | a module, and also vendors everything. | | This may require a few extra tricks to plumb through, for | example, to make all cmd's be externally importable (i.e. in | the project repository, transform "cmd/foo/%.go" from being an | unimportable "package main" into an importable | "cmd/foo/cmdfoo/%.go", then have a parallel "cmd/foo/main.go" | in the vendoring repository that is just "func main() { | cmdfoo.Main() }", same as you have in the project repository in | fact). | | Vendoring aside, this is also a useful pattern if you're | "go:embed"ing a collection of build artefacts coming from | another source, like a frontend HTML/JS/CSS project. | vardump wrote: | UPX 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 wrote: | Can 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? | Karrot_Kream wrote: | I'm curious, was the practice of using upx there before you | got there? We generally A/B test changes like this pretty | thoroughly by running load tests against our traffic and | looking at things like CPU and Memory pressure in our | deploys. | themerone wrote: | Every 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. | ashishb wrote: | Any source that you can cite for this? I'm not saying you | are wrong. I'm just curious to see more proof of this. | themerone wrote: | https://stackoverflow.com/questions/9219244/why-does-my- | appl... | mikepurvis wrote: | Also impacts startup time. Really it's only appropriate | for situations like games where you're very confident | there will be just one instance of it, and it'll be long- | running. | | And even then, it's of dubious value when game install | footprints are overwhelmingly dominated by assets rather | than executable code. | vardump wrote: | Normally operating system simply maps binaries, executables | and loadable libraries (.dylib, .so, .dll, etc.) into | memory. The cost is approximately same whether you do this | once or 1000 times. The code is executed from the mapped | area as-is. | | However, when a binary is compressed, this cannot work, | because in the file the binary is represented as a | compressed data. The only way you can work around is to | allocate some memory, decompress the binary there, map the | region as executable and run it from there. This results a | non-shareable copy of the data for each running instance. | | A random link about this issue in practice: | https://github.com/nushell/nushell/issues/4131 | ownagefool wrote: | So, I don't bother with vendoring my dependencies ( usually ), | but you have it the wrong way round. | | Vendoring would make it more likely you're gonna review the | changes, be ause you can quickly eyeball whether or not changes | look significant, which is something you often won't get out of | a go.sum change. | fsociety wrote: | Unless you import a dependency which totals several hundred | thousand lines of code. | tonyhb wrote: | Make your git commit history good? `go mod vendor` in a | separate commit to your PR changes. Review the commit with | local code changes. Easy. | bakoo wrote: | > There's no point in stripping a binary or even using UPX on | it unless you're targeting extremely low memory environments | | Deploing at a large enough scale, perhaps where other | optimization options aren't as good or even available, could | also be a target. | shellac wrote: | [flagged] | tptacek wrote: | I don't know, it's a complicated question, and it has nothing | to do with the article and asks for a big language fight. | kortex wrote: | 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. "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 wrote: | > 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 wrote: | There'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 wrote: | What are you comparing to and what do you think the shortfalls | are? What is a "modern" language? | icholy wrote: | Go has better dependency management than most modern languages. | cpuguy83 wrote: | "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 | SergeAx wrote: | > 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. | arriu wrote: | One thing I wish there was better support for is live debugging | and stepping through code. | poo-yie wrote: | You know about VS Code and GoLand? | puika wrote: | I 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. | maerF0x0 wrote: | I'd add "What's the best web framework?" and answer it with "No." | | (Go comes batteries included) | rollulus wrote: | That'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 wrote: | A 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, 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 wrote: | And 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. | baby wrote: | I'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. | revskill wrote: | Working with Go is boring but productive. Go libraries are | reliable, fast. It's more than enough to write good software. | athorax wrote: | The 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 | [1]https://github.com/cespare/reflex | agotterer wrote: | I've been very happy with Air - https://github.com/cosmtrek/air | puika wrote: | Just to add to the list there is also | https://github.com/cosmtrek/air | leetrout wrote: | Mentioned in reflex's competition section I am a huge fan of | entr | | https://github.com/eradman/entr | synergy20 wrote: | how about watchman? I use that one. | https://manpages.ubuntu.com/manpages/jammy/man1/watchman.1.h... | jweir wrote: | Since we are mentioning these, I use entr | | # Makefile test: `find * -name "*.go" | entr bash -c "clear; go | test ./..."` | | https://eradman.com/entrproject/ ___________________________________________________________________ (page generated 2023-05-23 23:00 UTC)