←back to thread

257 points pmig | 9 comments | | HN request time: 0s | source | bottom
1. honkycat ◴[] No.43096164[source]
After dealing with constant build issues between Java and Typescript and Node and Python: I love go so much. The package management alone makes it worth it.
replies(1): >>43096583 #
2. scubbo ◴[] No.43096583[source]
After dealing with constant build issues with Go, I hate Go so much. The fact that they've conflated "source code" with "consumable library" means that you need a special case in your CI to publish new versions of a library in Go vs. every other language that builds and publishes an executable, and any tooling that pulls from a private repository has to hack `git config` rather than authenticating like you would any other artifact repository.

And that's before we even get onto the "v2" nonsense[0], because apparently it's unidiomatic to continue developing your packages after you publish them. Actually.....given that this language arose at Google, I may be onto something...

[0] https://go.dev/blog/v2-go-modules

replies(2): >>43096762 #>>43097758 #
3. diamondfist25 ◴[] No.43096762[source]
Btw js/ts, python, and golang, which one do you find more productive with?
replies(1): >>43097048 #
4. scubbo ◴[] No.43097048{3}[source]
Hard to pick between Python and TypeScript - they have different strengths. TypeScript's type system is more useful (you'd hope, given the name!), but Python "just works" more often for simple use-cases IME (though I have well over double the lifetime experience with Python, so that might be a me-factor rather than a language factor).
replies(1): >>43104984 #
5. throwaway894345 ◴[] No.43097758[source]
I’m confused by this. Go doesn’t have a “publish a library” step, whereas every other language does. Is “noop” the special case you are referring to? And why are you comparing publishing a library in Go to publishing executables in other languages?

> unidiomatic to continue developing your packages after you publish them

Are you talking about publishing breaking changes without bumping the major version? Because that seems … like a bad idea in any language?

replies(1): >>43104853 #
6. scubbo ◴[] No.43104853{3}[source]
> Is “noop” the special case you are referring to?

"Well, yes, but actually no". It's _not_ a noop - to publish a new version of a library in GoLang requires tagging a commit in the source code repo. This, in turn, is tricky because there's no way to review a version bump during PR - unlike, say, JavaScript where a PR makes a change to `package.json`'s `version` field (which will be used to determine the version of the resultant built library), there is no in-code representation of what the version "will be when merged" of a change being reviewed. We've resorted to hacking-in a `version.txt` file which is updated and read by our version bump automation.

But that's not all! When making a _major_ version bump in a library, you also need to change the `module` line in your own `go.mod` to have a trailing `/v<n>` (e.g. https://github.com/Masterminds/semver/blob/master/go.mod#L1). Another special case - every other language's generic version bump automation logic is "update <file location> to hold the version", Go's is "IF bump is major, THEN update go.mod to hold the major version".

This is separate from the awkwardness that comes from "publishing" via source code vs. publishing to a binary repository, where the difficulty arises from `go mod download` needing to authenticate to GitHub, whereas every other language's build tools authenticate to the location where built libraries are stored (Artifactory etc.)

So, yeah, in fairness there are actually two separate annoyances here that I mistakenly represented as the same - "recording version in tags makes it impossible to review the version-bump _of_ a change-in-review" and "publishing source code directly, rather than built libraries, means pulling dependencies from private repositories requires messing with authentication". Forgive me - there are just so many friction points in GoLang's development process, it's hard to keep them straight.

> why are you comparing publishing a library in Go to publishing executables in other languages?

Eh - I guess my terminology was off there. I considered and avoided using the word "binary" instead of "executable" because idk if every language uses a binary format to represent the result of building their libraries. The distinction I was trying to draw was between languages that have a transformation process (building/compiling/assembling/whatever) which turns "source code" into "a <thing> that other code can depend on", and GoLang which...doesn't do that. To be explicit - yes, in all cases I'm talking about building and publishing the consumable representation _of_ a library repository.

> Are you talking about publishing breaking changes without bumping the major version?

No, I'm not. I agree that breaking changes need to be accompanied by a Major Version increment. I'm talking about how cumbersome it is in GoLang _to_ bump the major version that you depend on of a dependency library. You don't just have to update the dependency in your go.mod to `github.com/foo/bar v2.0.0`. Because the import path _includes_ the version, you need to update all the `import` statements throughout your code to use the new `github.com/foo/bar/v2` path. Pointless busywork - even worse than the endless `if err != nil` statements which can be defended on the tenuous grounds that they prompt an author to think about how to handle their errors - this import path change is _truly_ useless as a method to catch errors because, if there is a syntax-breaking change in the depended-upon code, that will be caught at build-time _anyway_.

An update to the major version of a library that you depend on is a Big Change, and should be treated with caution. I'm not advocating for doing it blindly or casually. But I don't believe that forcing a basically-cosmetic change to all the import statements _of_ the consumed module does anything to ensure caution.

7. fullstackchris ◴[] No.43104984{4}[source]
Baffling. If you're seriously saying package management for python "just works" and for go "always breaks"... I guess your either a troll, or you've never written production software. And I'm not talking some clever Jupiter notebooks used for some internal auditing or whatnot, I'm talking about customer facing software used by _at least_ 100 people. I'm 12 years in the game and Python has always caused me nothing but pain, while Go hasnt ever cost me a second of afterthought, working in multiple environments after nothing more than git clone. But, if you like making "virtual environments", a horrible shim gimmick which wasnt even supported by the language itself originally, be my guest!
replies(2): >>43106709 #>>43130267 #
8. honkycat ◴[] No.43106709{5}[source]
Agreed! python easily has the worst package management out of all of them!
9. scubbo ◴[] No.43130267{5}[source]
No, that wasn't what I was saying. I was asked a tangential question about which language I preferred; and considering the language _itself_ rather than the ecosystem, I find that Python is the one that typically "just works" - that is, the barrier between thought/design and expression is smallest.

I've repeatedly heard terrible things about Python's packaging, and I have to believe that they're true, even if I've never experienced them myself. And, yeah, you've guessed partially correctly - my own 14 years of professional experience have been primarily with Java and TypeScript, with Python being my language of choice for _personal_ projects. So - yes, I never have written production Python.

To once again be clear, I'm not making any claims that Python's packaging is better than Go's. I'm making two separate and unrelated claims (because the latter was prompted by a tangential question):

* For someone currently building development tooling for a polyglot company, Go's dependency-management system requires more special-casing (both for publication and for consumption) than the others combined.

* For me personally, when translating thoughts/algorithms/designs into code (without considering publication), Python is the language in which I can do so fastest and most intuitively. Never having published a package with it, I've never had to engage with that side of things - I believe folks who tell me that it sucks, but from the consumers' side `source .venv/bin/activate; pip install -f requirements.txt` has always works flawlessly for me.