5 ms·
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 w
by jchw 3y ago
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.)
- pjmlp 3y ago> Direct memory access through `unsafe`. Python kinda does through `ctypes`? 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. > Tightly integrated assembly language; just pop Go-flavored assembly into your package and you can link directly to it. Almost every compiler toolchain has similar capabilities - Statically-compiled code with AOT; no bytecode, no interpreters, no JITs. Like most compiled languages since FORTRAN.
- jchw 3y agoHuh? 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. > Like most compiled languages since FORTRAN. Yes. But you didn't list "compiled languages since FORTRAN", you listed: > Python (1991), Java (1995), .NET (2001), Smalltalk (1972), Common Lisp (1984), Ruby (1995), Perl (1993).
- pjmlp 3y agoFirst 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)
- jchw 3y agoI 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.
- neonsunset 3y ago[flagged]
- adgjlsfhk1 3y agowhat about Julia? it has all the low level features you would want and it's structs are c compatible.
- neonsunset 3y agoUnfortunately, I know very little about Julia aside from hearing good things about its application in scientific domain and it having interesting options for accessing SIMD which are similar to C#'s SIMD API. Someone else here could perhaps provide better context.
- geodel 3y ago> it isn't, I know how a good one looks like) Good. Just don't tell others lest they point out many shortcomings in your choice.
- neonsunset 3y agoWell, would you like to?
- pjmlp 3y agoI agree with everything besides the single language. Something like D or Nim would also count, although I do grant they feel like toy ecosystems when comparing with .NET.
- jchw 3y ago> Go is an extreme parody of C mindset adapted to kindergarten level of risk There's nothing of substance actually said here so it's hard to refute or support it very much. > so that Google could tackle its internal dev culture issues. Only one sentence in and this sounds like a vague reference to that thing Rob Pike said one single time 10 years ago or whatever, but I don't really care why Go was supposedly created or what it was for over 10 years ago, I care about what it is today. I think you can do better than this. > There is only a single high-level language with GC today that exposes appropriate low-level primitives and it is C#. In C#, you can declare C-style struct and pass it directly to C code across interop without any marshalling whatsoever. You cannot do this in the way everyone uses Go. I dunno what you mean exactly, you certainly can declare a C-style struct in Go. You can declare it using C, or you can pass a Go-defined struct into a C function, it follows roughly the same alignment rules, I do this all the time when coding against Win32 APIs. It's in fact better than it used to be because there is now a way to pin memory so that it is safe to pass Go pointers directly to C code, using `runtime.Pinner`, but certainly there was no limitation to using structs the C way before. There aren't many guarantees about memory layout, but there wasn't in C either. > I'm also amused by how "AOT" is one of the biggest demonstration of "X Y issue" in practice where developers have little understanding of how each platform can have drastically different ways of achieving "lean fast to start applications". What's unfortunate in this is they make Go's AOT as a selling point, where it's just its deployment model, at which it's not even the best nowadays OK... but for context... I was literally only trying to demonstrate that Go is a relatively low-level programming language in terms of how close you are to machine code, putting it in a similar camp to languages like C and Rust, rather than something like Python. It is not an argument in favor of a given way of packaging or executing software. You can of course make programming language implementations with different tradeoffs, but I don't think it's accidental that scripting languages, compiled bytecode languages and compiled machine code languages tend to have different attitudes, I'm of a mind that they are mostly the way they are because of the characteristics that would lead someone to reach for one versus the others. > you will be much better served by forgoing Go in favour of Rust or C# I don't think there's any reason to disagree that Rust is a great choice of programming language. Rust has numerous amazing advantages versus most other programming languages, offering an excellent set of guarantees. However, it does so by paying a lot of language cost to get there. I'm not saying, for example, that this means that Go is good at some use cases and Rust is good at others, I'm saying that Go and Rust have some overlap at what they are good at and they have some areas where one will have nicer tradeoffs than the other. Rust handily has the advantage for writing concurrent code, which is ironic given Go's name and how much its concurrency model was emphasized early on. But Rust is a very, very complex programming language; sometimes what it goes through great, great pains is something that you absolutely, 100% want to have, at any cost, and sometimes it's just not. When dealing with embarassingly parallel programs like network services with nothing-shared architectures, Go shines; it's pretty good at these. When every CPU cycle and byte counts, Rust wins against Go every single time, because it offers greater control and vastly more powerful compile-time metaprogramming. (Go offers essentially none, since even generics mostly compile down to interfaces.) Does the complexity always matter? Well, maybe not, but you'll notice in compile times. > please do not tell me about how good Go's standard library is - it isn't, I know how a good one looks like This is a shallow dismissal that shouldn't really convince anyone since it doesn't even attempt to paint the picture so I will reply with a retort of the packages in the Go standard library that I think are pretty great and I would like to have in other programming languages. - Literally all of `crypto`, including `crypto/tls`. To be completely fair, I wouldn't argue they are perfect (`tls.Config` is a little weird) but they are very clean and reasonable implementations of cryptographic routines including some nice optimized assembler code across many architectures for plenty of them. The actual interfaces are pretty good and help to avoid some basic pitfalls. It is relatively easy to e.g. create and sign an X509 certificate, versus OpenSSL. - `regexp` - Neither the fastest nor the most fully-featured regular expression engine. On the other hand, though, it gives you re2 behavior - the same featureset, and the same runtime behavior, specifically that it scales linear with time with regards to input size. That makes it a rather good library to have as a default choice, since it is significantly less likely to wind up as a surprise footgun that way, versus say PCRE. - `image/png`, `image/jpeg`, etc. They're neither the best nor the worst PNG or JPEG encoders/decoders. But they're PNG and JPEG decoders, in the standard library, and the speed they perform at it seems acceptable, and they're memory safe. For doing any serious amount of image processing, I'd rather shell out to libvips, but there are a lot of use cases where it's tremendously nice that there's basic codecs like this in the standard library. Same for the compression algorithms in `compress` and the archive implementations in `archive`. - The `go` package. Like most of the other packages, there's nothing terribly astonishing about this package. However, it does give you enough Go compiler guts to go ahead and parse and work with Go code. This is very useful because inevitably with large codebases you are going to want the ability to write accurate static analysis tools, make code that can do large tree-wide refactors, and other such tasks. For C++, you probably have little choice other than to use Clang's AST. For Rust, the closest I'm aware of is the `syn` crate, but I might be out of date here. These options generally require a great deal of effort to do even rather simple things, making it rather hard to get to the point of break-even for them, and I think that's not great. Some of this is definitely due to language complexity, but that is indeed a cost you have to pay multiple times. So it better be worth it!
- jmaker 3y agoI 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.
- norman784 3y agoI 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 https://www.youtube.com/watch?v=A3AdN7U24iU
- jmaker 3y agoThat’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.
- 3y ago