Go's standard library is a shining example of what all standard libraries should strive for. Yet, we still have some languages who's developers refuse to include even a basic http API in their standard libraries in an age where even embedded systems have started to speak http. Imagine if if the same had happened with TCP and UDP...
Here's to the continued success of Go and other sanely-designed languages.
Python (1991), Java (1995), .NET (2001), Smalltalk (1972), Common Lisp (1984), Ruby (1995), Perl (1993).
Go is following not leading.
To this day ISO C and ISO C++ still don't include TCP and UDP on their standard library, that comes from POSIX, the UNIX APIs that didn't make it into neither ISO C nor ISO C++.
Go is not quite the same but definitely on a similar level of abstraction to C, C++, Rust, etc. If that statement makes you raise an eyebrow, I'd suggest that while Go requires more runtime than C or Rust, it does still give you:
- Direct memory access through `unsafe`. Python kinda does through `ctypes`?
- Tightly integrated assembly language; just pop Go-flavored assembly into your package and you can link directly to it.
- Statically-compiled code with AOT; no bytecode, no interpreters, no JITs.
Therefore what really sets Go apart is that it gives you all of these rich standard library capabilities in a relatively lower level language.
Of course I kind of understand why Rust and C++ don't put e.g. a PNG decoder in the standard library, I think this is somewhat an issue of mentality; those are things that are firmly the job of libraries. But honestly, I wish they did. It's not like the existence of things in the standard library prevents anyone from writing their own versions (It doesn't stop people from doing so in Go, after all), but when done well it provides a ton of value. I think nobody would claim that Go's flags library is the best CLI flag parsing library available. In fact, it's basically just... fine. But, on the other hand, it's certainly good enough for the vast majority of small utilities, meaning that you can just use it whenever you need something like that, and that's amazing. I would love to have that in Rust and C++.
And after experiencing OpenSSL yet again just recently, I can say with certainty that I'd love Go's crypto and TLS stack just about everywhere else, too. (Or at least something comparable, and in fairness, the rustls API looks totally fine.)
Already available in ESPOL and NEWP (1961), Modula-2 (1978), Ada (1983), Oberon (1987), Modula-3 (1988), Oberon-2 (1991), C# (2001), D (2001) and plenty others I won't bother to list.
Almost every compiler toolchain has similar capabilities
- Statically-compiled code with AOT; no bytecode, no interpreters, no JITs.
Like most compiled languages since FORTRAN.
Huh? I think you misinterpreted what I meant to suggest that those features individually were unique or unusual. I was only using them to demonstrate that Go is on a similar level of abstraction to the underlying machine as C, C++ and Rust.
Yes. But you didn't list "compiled languages since FORTRAN", you listed:
First of all I never mentioned that I wrote an exaustive list of compiled languages since the dawn of computing, rather a reply to
"Go's standard library is a shining example of what all standard libraries should strive for. Yet, we still have some languages who's developers refuse to include even a basic http API in their standard libraries in an age where even embedded systems have started to speak http. Imagine if if the same had happened with TCP and UDP...
Here's to the continued success of Go and other sanely-designed languages."
You then moved the goal posts by talking about stuff that wasn't in that comment.
As such I am also allowed to move my goal, mentioning that
"Already available in ESPOL and NEWP (1961), Modula-2 (1978), Ada (1983), Oberon (1987), Modula-3 (1988), Oberon-2 (1991), C# (2001), D (2001) and plenty others I won't bother to list."
Are all languages that compile to native code.
"Ah but what about C#?!?", it has had NGEN since day one, Mono/Xamarin toolchain has supported AOT since ages, Windows 8 Store Apps used MDIL toolchain from Singularity, replaced by .NET Native for Windows 10 store apps, Unity compiles to native via their IL2CPP toolchain, and nowadays we have Native AOT as well.
And I will had that Java has had native AOT compilers since around 2000, even if only available as commercial products, with Excelsior JET, Aicas, Aonix, Webspehre Real Time, PTC, and unsafe package as well, even if not enjoying an official supported state (nowadays replaced with Panama for exactly the same unsafe kind of stuff and low level system accesses)
I do not understand how you and some other people seem to see a claim to be first in every feature a language ever says it has. Who is claiming primacy or uniqueness for almost any feature in any language ever? When has a Go designer ever claimed to be the first ones to implement a feature?
Programming languages have been largely just shuffling around features other languages have for the last 50 years now, and I can only go back that far because when you get back to the very first languages, they're unique and first by default. Even when a language is first to do something, it's generally only the first for a feature or two, because how would anyone even make a programming language that was almost entirely made out of new things anymore? Even if someone produced it, who would or could use it?
You seem to spend a lot of time upset about claims nobody is actually making.
It is the way people insist on writing such arguments.
I don't know what your goal in this discussion is. I don't think anyone is claiming Go invented having a nice standard library, nor is anyone claiming that Go invented compilers or anything weird like that. I think you misunderstood the entire discussion point.
On a similar note, iPhone did not invent cameras, MP3 players, cellular broadband modems, touchscreens, slide to unlock, or applications.
Except in reality in does not work, like you can't easily create a single binary out of most C/C++ project.
You always going to fight with make / GCC / llvm and other awful tools with errors that no one understand. It does not matter if the underneath tool / language is supposed to support it, can a developer make it work effortless or not.
In Go you download any repo type go build . and it just works. I can download a multi millions line repo like Kubernetes and it's going to work.
Depends on the C compiler one decides to use.
If you believe that regarding Kubernetes you're in for a surprise regarding reproducible container builds.
I think if the Rust team had the capacity they might have considered adding—and maintaining—more stdlib functionality. I never asked for details but I guess that the core Rust enjoys only a fraction of the funding Go and .NET have enjoyed. It’s not only a merits based decision case I think.
Regarding C++, it’s based on a standard, the situation is a bit different. You have a variety of implementations. Imposing anything beyond the typical use case the compiler implementations have catered to would induce an insurmountable overhead on the implementation coherence. Therefore, I believe it’s more reasonable to have application-level logic in the realm of community maintained libraries. In addition, C++ is huge syntactically and the stdlib is immense, but it’s more focused on algorithmic tasks rather than on quickly building mini-servers.
Besides, the Go community has a myriad of reinvented wheels, ranging from logging over caching to maps, and until recently HTTP server libraries. The logging story for example has just recently led to a discovery of the patterns desired by the community, mature enough to accommodate structures logging in Go’s stdlib. Similarly for error handling. Robust and settled approaches turned a de facto standard make total sense to be included.
.NET is different again, having a center of gravity with Microsoft and the .NET Foundation, with typically one preferred library for a given task, contrary to Java and Go. Centralized and decentralized, the classical dichotomy.
I think Rust team would still have a very small stdlib even if they have more funding, here's a talk[0] where they aim to be relevant for the next 40 years, in that time span there would be a lot of changes and to be backward compatible, you cannot have features in your stdlib that will be irrelevant or change in the next 5, 10, 15, 20 years.
[0] https://www.youtube.com/watch?v=A3AdN7U24iU
That’s a great point indeed. In Java and C++, there have been quite a few deprecations over the years and decades. In the Rust community, there’s unfortunately quite a lot of interesting but abandoned crates.
What changes are set to be made to the file format of PNGs that would prevent it from being relevant in the standard library 40 years from now?
I have deep respect for Python and like working in it, but Python's standard library has only one of the attributes listed on the comment you're responding to. The Go standard library is different in a variety of ways from Python's standard library, and, to the original commenter's point, it is far more common to replace portions of the Python standard library with third-party packages than it is with Go's standard library.
I love the, yes but, kind of arguments when people get shown how they aren't exactly right.
I take it you're using urllib2 to make HTTP requests in Python?
When the standard library does the job, there is no need to look elsewhe, unless forced to by third party libraries dependencies.
They're really not comparable standard libraries. For the most part, the "batteries included" features in the Go standard library are the idiomatically accepted versions of those features in the community, which is not something you can say about Python's standard library. It's a major difference. Using something other than net/http would be a code smell in Go code, but using urllib would maybe almost be a code smell in Python.
I think it’s a bit extreme to characterise it as sanity vs insanity. I think you need at least one of a large stdlib or good dependency management.
I love Go, used it since the 1.0 release and have used it at work for years. No complaints about the language. But for the longest time Go didn’t have quality dependency management and pulling in dependencies was annoying. Building your programs with the large, high quality stdlib was the path of least resistance.
Since Go 1.0 (2012) most new languages have coalesced on good dependency management. Rust, for example, copied Ruby’s bundler idioms since before 1.0 (2015). People who needed good quality libraries were able to pull them in with minimal hassle. That’s why they didn’t need a large standard library to succeed. I’ve written more about the tradeoff here - https://blog.nindalf.com/posts/rust-stdlib/
To you, I’d suggest using less charged language like sanity. In this case there’s a good technical case for both ways, and it’s not productive or nice to imply that people who choose a different path from you are insane.
I think there's a distinction between Rust and Go in that sense, Go has a clear objective, be a good (if not the best) language for writing web services (that's why Google developed it in the first place), that's why their stdlib is so rich to write this kind of applications, while Rust was developed to be the system language for the next 50 years, that's why the difference in stdlib.
The only downside of Rust is that you have to pull more than 100 dependencies to build a simple hello world server (Tokio + Axum | Actix), then you need a database driver, most likely something that depends on SQLx (not sure here how many, dependencies), but one of my projects got near 500 transitive dependencies with only 20~ish direct dependencies.
Go's objective was "C but with GC and async runtime". It got adopted for web services by chance, a better alternative to nodejs or python in some aspects, but the zero-values end up being a huge footgun to serialization which is the bread and butter of web stuff.
Rust dependency management is the best parts of Go with the worst parts of NPM.
You hit the nail with Go's initial purpose. That not only explains the high quality of the std lib in terms of http, but also the lower quality in other areas.
By the way: You still need a DB driver with Go. They just provide an interface, which is cumbersome and error prone to use. That's why the community package sqlx exists.
To create a hello world in Rust, one just needs to add two crates, which in terms pull many other crates. So yes, too many total deps for my taste, but an Axum server is much more feature full than a server build with Go's std lib.
To the grandparent, I'd suggest keeping the language as it is. Status quo in the current programming ecosystem is often insane, and when it is, we should call it out.
In a general sense, I agree. However, when it comes to programming, insanity is so widely accepted as normality that I think it would be counterproductive to blunt the language used to describe it.
As an example of insanity for those who may (justifiably) think I'm talking out of my bottom - in NodeJS ecosystem the standard library is so bad that it is considered acceptable to use dependencies for even the simplest tasks, which caused the `leftpad` incident which broke countless programs.
Leftpad is not appropriate here because Node.js didn't add any additional String methods anyway. Therefore it could have been prevented if JS proper had enough String methods beforehand, regardless of attitude towards dependencies. Grandparent's points in comparison are more about the scope of standard libraries. (And in terms of convenient String routines, Go is still a bit inferior to Python!)
Leftpad could've just as well be a part of some standard library, like...
... Go strings library :) https://pkg.go.dev/strings
Maybe I should've been more clear about "scope".
Standard libraries can pick their scope of functionalities and depth (or completeness) for each functionality. Nowadays every programming language is expected to come with a good string support, which is about the scope. But there are a lot of string operations you can support. PHP for example has `soundex` and `metaphone` functions for computing a phonetic comparison key. Should other languages support them as well? I don't think so, and that's about the depth or completeness because you can never support 100% of use cases with standard libraries alone. Ideally you want to cover (say) ~90% of use cases with a minimal number of routines.
Leftpad was clearly due to the lack of depth in JavaScript and Node.js standard libraries. JavaScript now has `String.prototype.padStart`, and an apparent name difference suggests a good reason that some standard library may want to avoid it: internationalization is complex. A common use case is to make it aligned by padding space characters, but that obviously breaks for many non-Latin scripts [1]. And yet many people tried to use it, so `left-pad` was born with a suboptimal interface, and we know the rest.
HTTP support is different. I totally agree that HTTP is something you want to support in a sorta native fashion, but a standard library is not the only way to do that. In fact it is not a good place to do that because it is generally slower to change (Go is a notable exception but only because its core team is very well funded and strongly minded). Python did support HTTP in its standard library for a long time, but it doesn't support HTTP/2 or HTTP/3 at all and Requests or urllib3 are now the de facto standard in Python HTTP handling. Modern languages try to balance this issue by having a non-standard but directly curated set of libraries. Rust `regex` is a good example, which may be surprising given than even C++ has a native regex support. But by not being a part of the standard library, `regex` was able to move much faster and leverage a vast array of other Rust libraries, and it is now one of the best `regex` libraries throughout all languages. That's what nindalf wanted to say by different "ways".
[1] For example, `"한글".padStart(5)` will give you `" 한글"` but its visual width is larger than 5 "normal" characters. This is not merely a matter of fonts and Unicode has a dedicated database for the character width ("East Asian Width"). Some characters are still ambiguous even in this situation (e.g. ↑), and the correct answer with respect to internationalization would be: don't, use a markup language or (for terminals) a cursor movement instead.
It's funny that your comment here applauds Go but your blog post praises Rust.
It is possible for more than one language to be good. Both languages succeeded with their approach.
“But how can you support two opposing sport teams, that doesn't make sense”
Too many people on HN when discussing about programming languages unfortunately…
sanity - Soundness of judgment or reason.
This doesn't sound extreme. The statement, "designed with sound judgement," doesn't carry the implications that you're defending from.
There’s also the philosophy that the language core should be as minimal as possible. I’m not 100% sold on it, but there’s definitely a valid argument to be made in favor of it.
As I wrote in another comment, it depends on the goal of the language, Go was build for writing web services, that's why they have most, if not everything, you need to write this type of apps.
Yes, I very much agree. The comment I was replying to however was referring to “other languages”.
My take as well. It's not black or white. At times I wish Rust's std lib was greater (by the way, it's not small either), but other times I'm blown away by the quality of some community crates.
Can you please not take HN threads into programming language flamewar? We're trying to avoid that kind of thing here - see https://news.ycombinator.com/newsguidelines.html.
We detached this subthread from https://news.ycombinator.com/item?id=39710822.
I really like that Go has a great std lib, but it comes at the cost of quality or at least feature fullness. Some examples:
- The csv package. Compare Go's csv package with Rust csv crate. The package in Go's std lib is close to useless compared to the Rust community crate.
- Logging. No tracing, limited providers, just recently added structured logging.
- The xml package is very slow and cumbersome to use compared to modern element-tree-like implementation. For larger docs you probably need to resolve to a community package.
- If I'm not mistaken, Java has a build in http server, which usage is probably very low. Instead people are using Jetty / Netty / Tomcat (? my Java times are long ago)
To repeat myself: I personally like the std lib approach of Go. I disagree to any narrow view on this topic.