The languages that have a poor standard library support have this issue and other languages encourage you to import tons of libraries to fix the problem.
This is why Javascript and Typescript suffer from this the most and has little to nothing to do with "popularity" and likely 9/10 of these npm packages import an external library.
Golang on the other-hand is just as popular and has a stronger standard library which people build against and it is encouraged to use its standard library rather than rolling your own or importing another package to solve the problem.
Rich official standard library vs "import tons of libraries" are not the only two options.
Java's standard library had arguably also been poor for a very long time and "import tons of libraries" just had not been practical for most of that time because the tooling and ecosystem for that did not exist yet.
The solution was apache-commons and guava. Two large libraries with everything the developers heart desired and well maintained by large organizations.
For Rust be probably will never have anything exactly like that because requirements from no-std development to fully fledged backend service are too diverse, but there is still room for a small number of well maintained backed by reputable developers convenience libraries in my opinion.
Namespacing. Mandatory namespacing. It's an essential prerequisite for any kind of reputation building and managememt, before you even get into the gritty technical or security details.
And it has to be mandatory. Top-level package names will always have more cachet. Developers are suckers for good package names, literal or imaginative. Plus it helps address, but by no means completely solves, name and typo squatting.
I understand people and groups can run their own crates.io-like repository, but that's a tangential aspect. Even if this were ubiquitous, you'd still want mandatory namespacing. You want provenance, or at least intended/nominal provenance, to be as transparent as possible, not implicit or buried. By no means a complete solution, but an important foundation for better technical and culture patterns.
I don't want to see a large standard library for Rust. If something is added to the standard library, then it is very difficult to change it afterwards because backwards compatibility.
It would be better to have blessed crates in crates.io. The Rust core team would release or audit them. If the blessed crates need breaking changes, it can be done by increasing their major semantic version number. That can't be done to the standard library.
Actually, there could be a "trust" level for crates: 1. blessed crates by the Rust core team, 2. trusted developers, 3. untrusted developers. Or something like that..
Go has a stronger standard library for certain use cases like basic CRUD web applications, but a lot of the Go standard library is also extremely low quality (flag, container, image, json, log, math, path, regexp, sync, time). Many of these aren't usable outside of toy use cases and have weird edge cases all over the place. Over time many will probably get new incompatible versions just like json. The container package in Go is the worst collection library in any mainstream programming language by a huge margin. It's actually astounding how bad it is.
FYI, json/v2 just dropped: https://go.dev/doc/go1.27#jsonv2 and log/slog has been a thing since 1.21: https://go.dev/doc/go1.21#slog
> a lot of the Go standard library is also extremely low quality
Now adjust your definition of "a lot" to include all other languages instead of apparently arbitrarily deciding that "a lot" means at best 10 and pretending that "weird edge cases all over the place" isn't normal.
I also wonder what your issue is with most of those, especially since e.g. regexp is excellent in the context of this thread - it runs in linear time, so it's not possible to craft a malicious input that will make it slow down to a crawl.
> Over time many will probably get new incompatible versions just like json.
What a bizarre statement to make.
FYI: "The encoding/json package is now backed by the v2 implementation.". You get all the benefits possible from the v2 implementation for free while maintating backwards compat and if you want to upgrade to something better, v2 is right there.
Do you have some magical suggestion how this could have possibly been handled better? And no, not having json in the stdlib isn't a viable path, that's just a cop out. But I guess since e.g. Rust and Java don't have json in their stdlibs at all, you can't say their json packages are bad, how clever and smart!
Another frequently made suggestion straight from la-la land is just writing perfect code from the get-go. Brilliant, can't believe nobody's ever thought of that.
Meanwhile in the real world, you've been able to reap the benefits of the solid encoding/json for over a decade now, and with v2 you get some nice free backwards compatible improvements and have a clear path to upgrading to v2. Perfectly handled IMO.
> Another frequently made suggestion straight from la-la land is just writing perfect code from the get-go.
The code in those packages is so far from perfect it's absurd. Like most Go developers, you just have extremely low standards.
I don't think this is true. People like to scapegoat the JS standard library but in reality most JS implementations have pretty featureful standard libraries, especially browsers. I've never felt the need to use any third-party libraries in the javascript projects I've worked on (except for maybe `ws`).
I don't think it's just that, though I agree they are clearly correlated.
The reason I don't think it's a sufficient explanation is that there is a clear history of large, 3rd party libraries being created exactly to supplement poor standard libraries. C++ has Boost, Java has Apache Commons (though Java also has a pretty huge standard library), arguably we could even say C has Posix/Win32/Cocoa.
I believe there is some deeper cultural reason why certain language ecosystems coalesce large utility libraries, while others prefer myriad tiny dependencies.
The important difference IMO is in the small vs big libraries culture.
Lots of languages have a bad stdlib but don’t fall into the trap of having thousands of micro libraries.
The reason people do it is because it brings clout and money. Just look for articles defending micro libs: the popular ones are by people who make a living on donations, due to maintaining 1000+ packages.
And collaborating in larger libs/stdlib is hard. Plus: Rust, Node, all have a lot of visibility.
You need a good stdlib culture to avoid it (like Go did).
The reason is simple: the package manager works well. Helps if the package manager is standardized and there is a "default" registry for open source projects.
I remember the days where I had to manually put the Spring .jar files into my project. No way I am doing that for 100s of dependencies.
I've never seen a non trivial Python or Go project without external dependencies. The dependency tree of comparable Go and Rust projects seem comparable, IMO.
Pytorch has 9 transitive dependencies for cpu-only execution, or 29 to bring in cuda.
candle, the most popular rust ml library I found in a cursory search, has 119 for cpu only, and 150 to bring in CUDA.
I guess it's taste whether that's comparable
this would have been a way more satisfying dunk if nvidia hadn't split the cuda functionality needed by pytorch into 19 (!) packages on pypi but such is life.
I expected somebody to pull out an example "disproving" my point. It wouldn't be hard. I can point out rust projects that have a ton of external dependencies, and then point at similar projects with very few.
But a Python example doesn't really count, in my mind -- Python is pre-GitHub so tends to have small numbers of large external dependencies, like C++ and other older languages.
If a python example doesn't count, why were your two example languages python and go?
But yeah, small number of large dependencies is the way to go.
Total nonsense. Python has a massive stdlib and there are malicious packages.
Can’t agree more. If you take security seriously, you should consider using Go.