Russ Cox is stepping down as the Go tech lead(groups.google.com) |
Russ Cox is stepping down as the Go tech lead(groups.google.com) |
Wonder what he’s going to do next? Maybe just moving around within G? or another OSS project within G?
I don't intend to make more of those, but that was a lot of fun.
Russ has also got a pull request to add an operator, see https://github.com/robpike/ivy/pull/83
Being able to use channels in a modern programming language is such a gift.
rsc thank you for all your contribution to our field. You blog posts also taught me a lot.
Golang is easily one of my favorite new languages. It's fast and clean without the difficulty of Rust. I was able to create a small mobile app with Chat GPT without any real experience in Golang.
I would like better mobile and gaming frameworks though. Although I really like Flutter, I think Google missed a major opportunity to use Golang instead of Dart.
What's next? Any good for native Chrome support?
>I would like better mobile and gaming frameworks though
er, try asking chatgpt to create them for you.
so you didn't really create it then did you? ChatGpt created it for you.
It's just another tool.
Go's obsession with glibc-isms is really unfortunate, and it's been many years. If you're using Go with containers on Alpine/musl, keep your code very vanilla, because they won't support you.
Go requiring non-ELF standard parameters for initialization of supposedly "C ABI" libraries, open since 2015.
https://github.com/golang/go/issues/13492
The Go project specifically acknowledging the glibc-isms here:
"All Linux first class ports are for systems using glibc only. Linux systems using other C libraries are not fully supported and are not treated as first class."
https://go.dev/wiki/PortingPolicy
Go only supporting static-init thread local storage, and thus their "C ABI" libraries can only be dlopen()'ed if the libc pre-allocates memory to hack in libraries later.
If you want to use c-shared mode and dlopen, then yes that only works with glibc, but that mode barely works at all anyway. It's not actively supported at all.
Its similar to calling the port overall “linux/<cpu-arch>” rather than “linux/<libc>/<cpu-arch>” which wouldn’t normally be called for except when you’re going to embed a bunch of a particular libc specific behavior in your consumption of libc.
Listening to Go advocates talk about C interop like it’s not only a solved problem but quite literally a strength of Go, while Go project leaders represent that support quite differently isn’t it. Perhaps clarification of these level of support terms and how the project embraces glibc specific behaviors unapologetically would help.
Other contenders I find myself sharing and re-reading:
- https://swtch.com/~rsc/regexp/regexp1.html
- https://swtch.com/~rsc/regexp/regexp4.html
At the time, the community seemed to have settled on dep - a different, more npm-like way of locking dependencies.
rsc said "nope this doesn't work" and made his own, better version. And there was some wailing and gnashing of teeth, but also a lot of rejoicing.
That makes me a bit sad that rsc is leaving.
On the other hand, I don't really like the recent iterator changes, so maybe it's all good.
Btw if you reading this rsc, thanks a lot for everything, go really changed my life (for the better).
Hope he gives us more in the future
thanks rsc
I’ve wasted so much time dealing with “module hell” in go, that I never dealt with in the prior years of go usage. I think it has some major flaws for external (outside Google) usage.
Ah, I still remember this thread:
https://groups.google.com/g/golang-nuts/c/rvGTZSFU8sY/m/R7El...
Separating the concept of pointers and nullable types is one of the things that I think go having from the beginning would have made it a much better language. Generics and sum types are a couple of others.
Ouch, who were they asking? There are so many problems from even the most simple CRUD apps where "lack of a value" must be modelled, but where the zero-value is a valid value and therefore an unsuitable substitute. This is probably my single biggest pain point with Go.
Using pointers to model nullability, or other "hacks" like using a map where keys may not be set, feel completely at odds with Go's stated goal of high code clarity and its general disdain for trickery.
I know with generics it's now trivially easy to implement your own Optional wrappers, but the fact that it's not part of the language or even the standard library means you're never going to have a universal way of modelling this incredibly basic and common requirement across projects. It also means you're never going to have any compile-time guarantees against not accidentally using an invalid value—though that's also the case with the ubiquitous (value, error) pattern and so is evidently not something the language is concerned with.
Go needs a null-like thing because the language forces every type to have a zero value. To remove the concept of zero value from Go would be a major change.
Iterators are very nice addition, even with typical Go fashion of quite ugly syntax.
Because of this change, Go 1.22 is actually the first Go version which seriously breaks Go 1 compatibility, even if the Go official doesn't admit the fact.
I think you are assuming more guarantees than are actually guaranteed.
You have a well-documented history of making incorrect claims about Go compiler and runtime behaviors, so this isn't surprising.
> since Go 1.22, you should try to specify a Go language version for every Go source file
What on Earth?? Absolutely 100% not.
I always assumed that it was considered faulty to do so.
Other than that, I agree with your comment.
It's interesting that the best projects have BDFLs, and that the best BDFLs are skeptical of their own power.
Despite playing around with several programming languages, Go still feels like home.
The development experience is terrific and I really appreciate how unapologetically simple and responsible the language and its creators have been.
Good luck and all the best in all your endeavours!
You're quite welcome, and thank you for this comment. I never expected when we started that Go would have such a positive impact on people's lives, bringing new people into programming and software engineering. That's definitely the impact I'm most proud of.
I do wonder, if you could re-do Go or another programming language again. What feature / changes would you add or take out.
Here is the first episode - devastating, convincing, easy to understand and very well written:
I disagree on one point that has nothing to do with Go. Python has not benefitted from GvR stepping down. The new "leadership" is non-technical, tyrannical and has driven almost all true open source contributors away.
Development has stalled except for the few corporate contributions of doubtful quality. The atmosphere is repressive and all that matters is whether you have a position of power at Microsoft/Instagram/Bloomberg.
It is not necessarily the fault of these companies. They may not know that their generosity is being abused.
Do you have some data to back that up?
The stats on Github seem to show healthy activity. 700+ merged PRs from 120+ contributors in the last month [1].
There seems to have been a big influx of new contributors in the last few years. [2]
I hate what autoformatters do to my code, but I love not having to talk about spacing anymore.
An LLM-based architecture for helping maintain OSS projects. Seems cool.
Thanks Russ.
I'm certainly thankful for golang as it made my https://github.com/purpleidea/mgmt/ project possible!
Thanks Russ!
And now he’s continuing the stretch of outstanding leadership by passing the torch. I can wait to see what the next 12 years of Go brings. Thanks for your service, Russ!
For example, if a language doesn't come with a built-in formatter that's a huge red flag. Go broke the tyranny of style discussions.
Easy static binaries is right up there for all new languages.
Kudos to rsc and team for all the work that went into making a great language. Good luck on your next projects.
Go is awesome and I hope it will continue to progress in that direction. Thank you Russ Cox
Go evolves slowly but steadily. No drama, no politics (external, I don't know about the internal), not social justice wars, just great technical and community work focussing on the thing at hand: A programming language and ecosystem.
thanksStr := "thank you rsc"
ret, err := sayThanks(thanksStr)
if err != nil {
return nil, err
}
return ret, nilThanks for your leadership of the Go team over the past 12 years, and for your patient comments and guidance on our proposals and PRs.
Best wishes for the future, and hope to see you in the community again.
If you learned idiomatic go, you can maintain and patch other libraries in the ecosystem very quickly.
Unified codestyle, unified paradigms, unified toolchain.
It's a language with harsh opinions on everything. If you manage to get over your own opinions, you'll realize that any opinion upstream is better than no opinion downstream.
That's why go's toolchain isn't as messed up as npm, yarn, grunt, gulp, webpack, parcel, babel and other parts of the ecosystem that have no conventions and are therefore as a result very expensive to maintain.
I suppose in theory it's some independent entity/commitee/whatever, but who pays the majority of the people working on it? Google?
Checking the 20 top contributors from https://github.com/golang/go/graphs/contributors
Google: 10
Unclear: 7
Tailscale: 1
Canopy Climate: 1
Isovalent: 1
Just checking the GitHub profile and not doing any deeper digging, so take it with a grain of salt.Caddy and docker pop right into my mind. I‘ve also seen databases, image processing and other nitty gritty systems programming related projects in Go.
People also love to write CLI apps in Go that do a lot of heavy lifting like esbuild or k6 etc.
The sweet spot for Go seems to be IO heavy programs. It allows for just enough control to get good performance for a lot of use cases that bleed into systems programming.
And neither Zig nor Rust have replaced C++ to any meaningful degree. Nearly everywhere it would count I still will have to deal with C++ for years, if not decades, to come.
As compared to people who want to be leaders, for the sake of being known as a 'leader', but have neither the competency nor accountability to be leaders.
The best leaders are interested in being leaders for the betterment of their team/community, not for the clout. But people who are pushed to be leaders without being interested in that, they tend to suck and make life miserable for everyone else. Leadership is a skill, if you treat it differently, you will suck at it.
Meanwhile there's entire landfills of failed projects with single owners who couldn't bend enough. We just don't find this worth discussing.
Of course this won't happen, but a man can dream.
* Keras
* Ruby
* Clojure
* Zig
* OCaml
* Vim
* Elixir
I think all of these have ended up being unusually coherent. I may not agree with their design philosophy, but there clearly is one.
This extends well beyond OSS projects.
Strongly disagree. Beyond very simple codebases lack of generics means either duplicating a bunch of code or eschewing type safety - neither of those things are particularly attractive to me. I can't imagine writing code in a strongly typed language that doesn't have support for generics.
Even if you don't use them directly it's almost certain you're using libraries that would be forced to be less ergonomic or type safe because of a lack of generics.
Type casts are checked.
> that doesn't have support for generics.
We get first class functions and compiled closures with zero syntax overhead. It's entirely manageable.
> or type safe because of a lack of generics.
Case in point: sort.Slice(). It lacks ergonomics, otherwise, entirely usable.
That being said, the generic version is faster and easier to use, so they are not without purpose, but they're not fundamental to large scale design either. Used without caution they can become a burden in and of themselves.
I like them just fine, but I could completely live without them.
I strongly disagree. Sure, like anything in programming, generics can be misused. But even comments can be misused!
OTOH I am able to build things in Go with generics that I would not be very happy building without them.
But generics as a high-level concept are wonderfully simple and useful ("let me use different types with certain code constructs without having to manually duplicate them, and stop me from doing anything that doesn't make sense"). It would be a far easier call for languages to add them if they were just a bit of syntactic sugar instead of a whole new section in the manual. (I do think adding generics was a good call; practicality trumps a fussily clean design, in my book.)
And arguably are in Go, where they are used for all kinds of things that are not inline documentation!
That doesn't look like is going to happen — the leadership change announced here seems to me to continue on the Google path. Both Austin and Cherry are relatively unknown outside Google and are to my knowledge not active in the community outside Google.
I don't believe this is true at all. They are both highly active in external Go development, far more active than I have been these past few years. (It's true that neither gives talks or blogs as much as I do.)
What does this even mean? Google basically just finances the project, but doesn't really "control" anything, never mind that "Google" isn't a monolithic entity in the first place.
I trust specs[1], multiple implementations[2], and how easy it is to bootstrap a compiler[3].
[2]: https://gcc.gnu.org/onlinedocs/gccgo/ (even if feature parity isn't quite there yet)
[3]: Instead of requiring double-digits compilation steps that each take too long to be reasonable.
New Jersey vs. what? I read about that phrase sometime earlier but forgot the rest of it. Is it vs. MIT / Stanford / West Coast / other? implying worse is better vs. other?
is it also related to neat vs. scruffy approaches in AI?
too much in tech to keep track of it all.
but asking out of interest.
source?
https://news.ycombinator.com/item?id=40997745
https://news.ycombinator.com/item?id=40184763
Among others. Again I'm not saying I agree, I'm just saying you don't see the same with Go.
Which isn't surprising to the rest of us. If you remember the days before Go, every second thread on HN was about how "company X", including the company now known as X, saw their Ruby network servers completely falling down under load, forcing a rewrite in whatever the language du-jour was that day. But Googlers tend to live in a completely different bubble with respect to the way software is written.
It is pretty clear that with respect to that goal, Go is a success. It has attracted Python programmers who need type safety and performance. Someone with no Go experience could land a useful new feature in a big Go program in 3 months.
Introducing a junior person to a large Rust system would still take a year, because it is so much more difficult than Go. Which means to me that if Rust had been aiming at this same adoption goal (it wasn't) it would not have succeeded where Go did.
A recent study done at Google disagrees with this assessment.
""it takes about the same sized team about the same time to build it, so that's no loss of productivity",
said Google's Director of Engineering Lars Bergstrom about porting Go to Rust in the talk https://youtu.be/6mZRWFQRvmw?t=27012
Do you really think large Golang codebases are so easy to survey? I could see the argument wrt. C++, but Rust actually has a great featureset for programming "in the large". Take a look at the k8s codebase for an example of a large project that's written in Golang - doesn't seem all that easy to get started with.
What I am more curious about is how much actual use Go has within companies and especially Google. What is the percentage of Go within their monorepo? How much of Google search is powered by Go?
It was supposed to replace C++ in projects where the developers would’ve otherwise reached for C++ simply because it was the default language choice.
return sayThanks(thanksStr)
I've seen this "if err != nil" pattern before, but I can't help thinking that it's not necessary."return ret, nil" ignores err's value, which is nil anyway.
"return nil, err" ignores ret's value, but why? If the caller checks for err before doing anything with ret, it doesn't hurt having ret always passed up.
4 extra lines only to lose the value of ret in case of error.
return sayThanks("thank you rsc")
without losing anything, but then it could just as easily be JS.Usually the pattern is used to perform better error handling (wrapping errors) or in case you call multiple functions that might return an error.
In this case, your suggestion is actually what I would expect to see
Imagine in Java or Python or C# or ... many languages that use exceptions to handle errors:
return a(b(c(arg)));
...where a(), b(), and c() can throw some kind of exception, so you don't have to handle them then and there. In Go there aren't exceptions, all error handling is explicit and handled conventionally by returning an error as the last (sometimes only) return value, which isn't composable, so you get: cVal, err := c(arg)
if err != nil {
return nil, err
}
bVal, err := b(cVal)
if err != nil {
return nil, err
}
return a(bVal) // the final call can be simpler
That's the minimum verbosity required. Since Go 1.13 (2019), they officially added the concept of "wrapped" errors (aka "cause" in languages with exceptions) so instead of returning err you can return errors.Wrap("error in the a-b-c function calling c", err). But nonetheless, _every_ level of the call chain has to wrap or pass on all errors with explicit code. Go does have panic() and recover() which allow for exception-like error handling but it's not idiomatic to use them for normal error handling, go wants that to be explicit.As for why "return nil, err" rather than "return ret, err"? Because while the caller _should_ check for errors, sometimes they just don't.
ret, _ := abc(arg) // just ignore the error
ret.DoSomethingFun()
You as callee don't want to get the blame if you've _partially_ filled an struct because you returned early with an error, and it's then usable but causes a crash because it was partially initalised, because someone ignored the error they got when creating it. That hides where the problem really was. Better to return an empty value, default value or nil. return nil, fmt.Errorf("expressing gratitude: %w", err)While you're still reading these, I want to say that while I've never ended up using Go for any shipping projects, I've been a fan since day 1. And it hasn't been lost on me that in the languages and ecosystems I do use in my professional life, good decisions from Go have propagated through the software world.
One thing that really sticks in my brain is gofmt; it makes it clear that there's still relatively low-hanging fruit where you can make a really good decision that spreads to the rest of the world on merits alone. It's an inspiration.
I didn't study the reason why Go chose this way over others. I do know they've considered other ways of doing it and concluded this one is best, based on complex criteria.
People who make value judgements like this typically ignore those complex consideration, of which playing well with all the past Go design decisions is the most important.
Frankly, you didn't even bother to say which language does it better or provide a concrete example of the supposedly non-ugly alternative.
I'm just also watching your YT video on testing and enjoying it very much!
And there are a large quantity of private Go code in the world.
The authors of the change did try to prove such cases don't happen in practice, but their proving process is totally breaking.
It is my prediction that multiple instances of broken cases will be uncovered in coming years, in addition to the new foot-gun issues created by the altered semantics of transitional 'for' loops.
As opposed to the "MIT style".
Related: Featuritis vs. YAGNI.
"When we have rewritten from Go into Rust, we found that it takes the same size of team and same time to build it."
Important part here being: rewrite. I would expect a rewrite to take less time, not the same time, than writing from scratch. Yet a Rust rewrite took as long as Go from-scratch project.
So to me, this implies the opposite, that Rust takes longer to write.
Go is much more optimised for quick onboarding, fast feedback, more “code look” consistency across projects then rust.
Now a team that knows both rust and go well might have the same proditivity in rust and go (maybe even more in rust), but with lots of changes in personell, specifically in quick growing departments, go can make a huge difference.
This is obviously just an anecdote, but i’ve seen more companies or departments running mostly a go backend stack, having job postings saying “no go experience required”, than the equivalent other companies (or departments ) focused on any other lang.
telemetry design is actually very thoughtful, limited and reasonable about what and how much data it sends. Motivation for sending the data is clear (improving Go). It's only a scandal for unreasonable people.
And I think there are many similar people like me.
There are few languages that are safer and easier to maintain, imho. The typesafety is superb.
It looks you don't understand the change at all.
The statement "since Go 1.22, you should try to specify a Go language version for every Go source file" is made officially, not by me.
> You have a well-documented history of making incorrect claims about Go compiler and runtime behaviors, so this isn't surprising.
The claim is totally baseless.
All my opinions and articles are based on facts. If you have found ones which are incorrect or which are not based on facts, please let me know: https://x.com/zigo_101.
Please provide a link to documentation on golang.org. Note: not a comment in a GitHub issue, not a blog article -- official stuff only.
> baseless
It should be evident by the consistent responses to your GitHub issues that nobody takes you seriously. Which is unsurprising, when you make recommendations like
> Anyway, since Go 1.22, you should try to specify a Go language version for every Go source file, in any of the above introduced ways, to avoid compiler version dependent behaviors. This is the minimum standard to be a professional Go programmer in the Go 1.22+ era.
To begin with, zero values were never a great idea. It sounds better than what C does (undefined behavior), but zero values can also hide subtle bugs. The correct approach is to force values to always be initialized on declaration or make use-before-initialization an error.
Having said that, it was probably too late to fix zero values by 2009, when Go was released to the public, and this is not what the thread's OP suggested. He referred to Eiffel, which is an old language from the 1990s (at least?) that didn't initially have null-safety (or "void-safety" in Eiffel's case), but released a mechanism to do just that in 2009, shortly after Tony Hoare's talk at QCon London 2009 (no idea if they were influenced by the talk, but they did mention the "Billion Dollar Mistake" in the release notes).
Eiffel's added nullability and non-nullability markers to types (called "detachable" and "attached"), but it's also using flow-sensitive typing[1] to prevent null-dereferencing (which is the main cause for bugs).
The thread OP didn't ask to eliminate zero values or nullable types, but rather requested to have a non-nullable pointer type, and flow-sensitive typing.
If structs need to be zero-initialized, a non-nullable pointer could be forbidden in structs, or alternatively Go could make explicit initialization mandatory for structs that have non-nullable pointers. At the very least, Go could support non-nullable pointers as local stack values, and use flow-sensitive typing to prevent null dereference.
A very widespread system for organising people is to have a single responsible decision-maker, supported, monitored and advised by a committee. We see that through politics and business, and a lot of the best open source projects seem to do the same thing.
Many of those, including Linux as far as I know, simply started as projects that were driven by single authors with a strong vision and remarkable diligence.
Then people flocked to those projects, but with the understanding and appreciation of that vision.
I don’t think any of them wanted to be BDFLs for the sake of power. They were the original authors and _made_ something useful. I don’t think any of them took over an existing project and declared themselves dictators. Ironically they all would be way too opinionated to do so.
Also I've never seen Torvalds "chewing out people on mailing lists for something stupid they said", it's always been someone breaking something or something along those lines. That is: doing stupid. And it's also experienced maintainers Torvalds feels should have know better.
You can like or dislike Torvalds' style, but this little student from Finland created the world's most successful open source project, so I think he's probably doing one or two things right.
He may not be perfect, but being hung up over a few incidents over a 30-year time period is perhaps not too brilliant, and insinuating incompetence over this is quite the take. Imagine every outburst you have is public and pointed to for years to come.
Not only is this a complete lie, but God forbid there's a process in place to catch these things instead of verbally abusing your coworkers for making mistakes, which Linus has done himself.
> Imagine every outburst you have is public and pointed to for years to come
You may be surprised to learn that the rest of us don't talk to anyone like this.
> but being hung up over a few incidents over a 30-year time period
That's a great way to make it sound old but he actually gets angrier as time goes on. https://lkml.iu.edu/hypermail/linux/kernel/1510.3/02866.html
Linus doesn't even rant frequently either. People point to the same 10 messages over and over again.
He also tolerates when someone snaps back at him, unlike in projects with double standards like CPython where the old boys can do whatever they like but you are not allowed to criticize back or point out their numerous mistakes, segfaults, threading bugs and generally low code quality.
Who is "they"? Who is "the community"? Who qualifies for a vote and who doesn't? I never contributed any code to the Go compiler or stdlib, but have contributed to some aspects of the "wider ecosystem", including some things that see fairly broad usage, and am (coincidentally) wearing a 2018 GopherCon t-shirt as I write this. Do I qualify? Does someone who has been writing Go for a year qualify? A week? Someone who never even wrote Go code? Someone who sent in a single patch to stdlib? And how do you verify all this?
Saying "let the community vote" is easy, but if you think about it for more than a second you will realize there's tons of difficulties and that it doesn't really work. I also don't really know of any project that works like this: it's pretty always a fairly small group of "core contributors" that get to decide.
Python, Postgres, Rust..
A small amount of core contributors doesn't mean they all have to come from a single corporate entity either.
The notion that only Google could shepherd a programming language is hilarious.
I never said anything of the sort. I said that "let the community vote on who new leaders are" doesn't work. Python, PostgreSQL, and Rust don't work like that either; it's just members of a fairly small "core team" that can vote, or some variant thereof. I have no inside knowledge here, but I'll stake a good amount of money that the Go core team had a lot of discussions about this, and de-facto, it's more or less the same as having a vote – except maybe a bit less formal.
And Go would obviously be fine without Google, just as Rust was fine without Mozilla. But why bother? It's working fine as it is and Google wants to spend the money on developer salaries, so why not let them? People get far too hung up on "Google bad". I say this as someone who doesn't even have a Google account or Chrome installed.
I've worked at Google, I've used Go for about 8 years at this point and I've met a few of the key Go figures at some point. I have to say that I have _no_ idea who would be best to run the project. And neither do you.
This isn't politics where the winner gets to vanquish their enemies and make themselves and their friends and family rich. It's developing and maintaining a programming language. The only real reward you'll get is admiration IFF you do a good job. Do a crap job and you ruin the project and/or become a pariah.
I would rather have those people who make up the core leadership tell me who should run the project since they not only know the technology, but they know the people and they know how to provide continuity. Continuity and discipline is all-important.
I'd prefer it if whoever runs the project works for Google since that is where Go was born. In part for continuity reasons and that Google has proven to be a very good home for Go, but also because it is good to have direct access to an organization that has resources to support you.
An integer range is a very basic type, too, conceptually, but many languages don't support them in the type system. You get an unsigned int type if you're lucky.
Not really, its semantics get hairy almost instantly. Eg does it incrementing it produce a new range?
Or do you give up on answering that and simply prevent adding strings and integers? When one wants to add them they can first manually apply an appropriate type conversion.
That is certainly a valid way to address your question – i.e. don't allow incrementing said type. Force converting it to a type that supports incrementing, and then from that the developer can, if they so choose, convert it back to an appropriate range type, including the original range type if suitable.
Of course, different languages will have different opinions about what is the "right" answer to these questions.
Just signed vs unsigned makes this a complex topic.
Generics are a basic language feature for a statically typed language. Go needs a lot more features to be usable, like better error handling, but the ultra-conservative community that opposes any changes is a drag on the language and makes developing in it a miserable experience.
I guess what I'm caught up on is the idea of "usable" is entirely subjective. To my eyes and fingers, Go has been fine without generics, and since their addition I've only used them once to clean up an odd bit of code around instantiating "module" like initializers.
> and makes developing in it a miserable experience.
Subjective or not I find this a bit harsh. I spent years in an environment where C was the only option that could be used and Go is a complete dream compared to this. You may dislike the environments, you may find fault with them, but there are many examples of both of them being used to build large and complex systems that aren't completely "miserable" to work on.
I wonder if the split is something like "batteries must be included." I don't feel this way. I'm content to mine up Zinc and Copper and forge my own batteries if needed. I'm not at all put out by this.
You have been using a generic data-structure since Go 1.0 but did not realize this.
ok errors.As is a little stupid, I'll give you that. But that's all.
Can you name 3 apps/projects that use COBOL?
-- This is akin to asking, "Quick, name 3 books written in Persian. Huh, you cant name them? Must be a dead language"
Does this imply that you see COBOL as having a trustworthy future, making it a great choice for a new greenfield application?
iow, the first part does not imply the second part.
a lang could have a trustworthy future for maintenance of existing apps, like in terms of support from vendors, while not being a very good choice for greenfield applications, due to not having modern language features and libraries.
but there is so much cobol in critical infrastructure in the world that I don't think it is going away anytime soon. Google for some relevant threads on hn about it.
there is a good chance that some services critically important to you and your family rely on software written in COBOL running on mainframes. just like for everyone else in the developed world and some of the developing world.
Go had both generics and iterators from the get go. Just not user defined ones.
Thus it is obvious that the creators of the language always saw their need for a simple and productive language
There is close to zero practical need in user-defined generic types and generic functions. Go 1.18 opened Pandora box of unnecessary complexity of Go specification and Go type system because of generics. Users started writing overcomplicated generic code instead of writing simple code solving the given concrete task.
Generics also allow to write some data structures that would be useful e.g. to speed up AST parsing: writing a custom allocator that would allocate a large chunk of structs of a certain type previously required to copy this code for each type of AST node, which is a nightmare.
This sounds like a good application for Go interfaces (non-empty interfaces). The majority of generics Go code I've seen could be simplified by using non-empty interfaces without the need of generics.
But what can we do against of this? This what I think: - stuck to use Go 1.16 - fork Go 1.16 and continue develop lang from there - learn OCaml... - give up and consume what these people decide to add to lang next and everytime feel disgust
I think Rust is better divorced from Mozilla, and Go would be better if it was divorced a bit from Google for a lot of the same reasons.
I don't really follow what you mean with that.
People keep going on that Big Tech needs to invest more in open source projects and maintainership. "But no, not like that!" Hmkay...
In the end, the people doing the work get to decide. That's how it works everywhere. Go originated at Google and many (though far from all) of the core people working on it are still paid by Google. The people doing the work seem to have no problem with this relationship, so standing on the sidelines shouting "no no, do the work differently!" is not really brilliant IMO.
And as I said, I don't see Google "controlling" anything. What does that even mean? Larry Page deciding what happens in the next Go release or something?
Did you mean replace `map[string]string` with `map[string]interface{}`? You should take a look at Go's runtime map code. This is not a "generic" data structure. It's an unsafe data structure with some thin compiler sugar on top of it which is also something worth taking a look at.
For example see how it handles something like `m["x"]` versus `m[12]` or a map using structs as keys. Put it in Godbolt then chase down the various runtime implementations you encounter. Unless I'm misunderstanding you, then I apologize, but what else did you mean?
> explain to all your stakeholders that you have done so because generics is bad.
I also write code based upon engineering principles and not on the difficulty of explaining it to my peers or customers. I'm more concerned with the results they experience when they use the software.
> generic data-structure
What we call "go generics" has nothing to do with "typed go maps." To the extent that I've needed something "generic" up until they were formally introduced into the language careful interface design was enough to cover 90% of use cases. For the ones that weren't a map holding a function which wrapped a type-checked cast operation did the rest.
So all we're left with is the ability for the current go generics to automatically populate functions into your compiled image based upon instantiated and optionally constrained type usage rather than some explicit and planned mechanism implemented through interface.
> I also write code based upon engineering principles and not on the difficulty of explaining it to my peers or customers.
I believe that difficulty of explaining code to "my peers or customers" is a basic engineering principle.
Also, I consider what the compiler does behind the scenes as irrelevant as long as you have reasonable performance and usability qualities. That's one of the fundamental principles of abstraction after all.
Btw, the inventor of the C programming language also said this. Dennis Ritchie -> "Code should be written for humans first, machines second"
The moral superiority is misplaced:
https://news.ycombinator.com/item?id=41017195
But I am not surprised. CoC proponents universally do the same as the people they criticize. Only the application of rules is selective.
Wild that you both made an account for this and dug through my comments just to comment on a comment on an article you didn't read.
You do. By outright claiming that I'm lying when I share what I've seen. Of course with no substance to back it up. Let me tell you: I've seen what I've seen. Have I seen an incomplete picture? Almost certainly. Am I wrong? Perhaps. Am I lying? No. Your post is extremely aggressive, pretty darn toxic, and explicitly the sort of stuff that's not appropriate here.
Do better next time. Doubly so if you want to get all high and mighty.
> Only those instances make the news. And then get repeated time and time again. It's a super-biased view not at all representative of his day-to-day behaviour.
You certainly can't represent your post as "I've only seen what I've seen" with that opener. You were claiming the OP was spreading misinformation. That is the lie. Which is why I provided an instance of Linus's tirades that doesn't match up with what you said.
Don't call someone "super-biased" and then be surprised when people don't roll over for you.
> Your post is extremely aggressive, pretty darn toxic, and explicitly the sort of stuff that's not appropriate here.
It's ironic that my mild comment is upsetting you while you defend a mans right to say his employees should've been aborted. Is it just because he's famous? Or because you think the employees were being stupid? Have you considered that "doing stupid" is a subjective assessment that people use as a cudgel to act poorly? What if I thought you were doing stupid, could I say the things Linus says?
Here's some more for you: https://lkml.org/lkml/2012/7/6/495
The original statement was about a range type, that is something like an integer that is statically constrained to a range of, say, 1..4 (1, 2, 3, 4).
To work with this as a type you need to have type level operations, such as adding two ranges (which can yield a disjoint range!), adding elements to the range, and so on, which produce new types. These all have to work on types, not on values. If 1..4 + 5..8 = 1..8 this has to happen at the type level, or, in other words, at compile-time.
Range types are very complicated types, compared to the types most people deal with.
Converting a string to an int is very simple to type (String => Int if you ignore errors) and adding integers is also simple to type ((Int, Int) => Int)
But such a thing would be useful mostly for fields in data structures, and the runtime checks would add overhead. (Though, perhaps it would replace an array bounds check somewhere else?)
The quoted part above is an argument for dependent types. The conversion back to a range type creates a type that depends on a value, which is the essence of dependent typing.
All reference types should be able to take a null value.
It's impossible to write complex and performant programs without null.
It's impossible to write complex and performant programs without pointers.
References always hold a memory address in a linear address space. (Not even true in C!)
Every type is comparable.
Every type is printable.
Every type should derive from the same common type.
All primitive types should support all kind of arithmetic the language has operators for.
The only way to extend an existing type is to inherit from it.
What else?
Well, I'd rather not copy around a multi-hundred-megabyte (or gigabyte) 3D object around to be able to poke its parts at will.
I'll also rather not copy its parts millions of times a second.
While not having pointers doesn't make impossible, it makes writing certain kinds of problems hard and cumbersome.
Even programming languages which do not have pointers (cough Java cough), carry pointers transparently prevent copying and performance hits.
The operations written in a program must literally represent the operations the computer will execute.
This one stops being true on high-level languages at the level of x86 assembly.
And in some languages, where you only operate on values, and never worry about where something is stored, allocation is just an implementation detail.
Example in C:
void fun(void) {
int a[16];
for (int i = 0; i < sizeof(a); i++)
{
a[i] = 1;
}
}I have allocated and referred to memory without pointers here.
It’s 2024, every type is jsonable!
Well, clearly there is a need for a special value that is not part of the set of legal values. Things like std::optional etc. are of course less performant.
If I can dream, all of this would be solved by 72-bit CPUs, which would be the same as 64-bit CPUs, but the upper 8 bits can be used for garbage collection tags, sentinel values, option types etc.
There's a neat trick available here: If you make zero an illegal value for the pointer itself, you can use zero as your "special value" for the std::optional wrapper, and the performance overhead goes away.
This is exactly what Rust does, and as a result, Option<&T>, Option<Box<T>>, etc are guaranteed to have zero overhead: https://doc.rust-lang.org/std/option/index.html#representati...
https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/cheri...
Address space is 64bit, pointers are 128bit, and encode the region the pointer is allowed to dereference. And there's a secret 129th bit that doesn't live in the address space that gets flipped if the pointer is overwritten (unless it's an explicit instruction for changing a pointer)
And the dismissive tone of some people including Ian. But to be fair before Rust there was definitely this widespread myth in the dev hivemind that nullable pointers is just the cost of performance and low level control. What’s fascinating is how easy and hindsight-obvious it was to rid code of them. I’ve never had to use pointers in Rust and I’ve worked on quite advanced stuff.
The benefit of Go’s generator implementation is a huge simplificación of the language semantics compared to other approaches. The generator function has no special semantics at all, and when used with ‘range’, all that occurs is a very simple conversion to an explicit loop repeatedly calling the function. Other popular approaches require either special runtime support for coroutines of some form, or a much more elaborate translation step within the compiler.
It's not that hard to understand what OP means.
"Assembly is not a low level language" is my favorite take, and with microcode and all the magic inside the CPU, it becomes higher level at every iteration.
Here's something to try at home .. exactly your code save for this change:
i[a] = 1;
... guess what, still compiles, still works !!WTF ??? you ask, well, you see, X[Y] is just syntactic sugar for X+Y - it's a pointer operation disguised to look like a rose (but it smells just the same).
I assume you mean by only allocating on the stack? Those are still allocations. It's just someone else doing it for you.
> And in some languages, where you only operate on values, and never worry about where something is stored, allocation is just an implementation detail.
Again, that's someone else deciding what to allocate where and how to handle the pointers etc. Don't get me wrong, I very much appreciate FP, as long as I do information processing, but alot of programming doesn't deal in abstract values but in actual memory, for example functional programming language compilers.
Yeah, that’s the entire point. Type safety.
You'd have to start by constructing replacements for all those mechanisms, then migrate all Go source code in the world over to the new APIs, just to enable Go to have types without zero values.
- You need to be able maintaining code with multiple ways to iterate over various collections in standard Go packages.
- You need to spend time on deciding which approach for iteration to use when you write new code.
In Go, a feature needs to have an extremely good reason to be added, and even then it's only added with care and caution.
In other languages, pointless features are added because maintainers are afraid, or not empowered to say... "yeah, we get it, but no, we will not add cruft to the language because you can't write your own 2 line function to achieve the same, no matter how hard you dunk on us on Twitter, it's take it or leave it, but you won't tell us how to run this project"
I wouldn't have described language designers' feelings that way, but you're absolutely right. For example, witness the recent features added to Python with little more justification than "other languages have it". It's pure FOMO - fear of missing out.
I mean granted, Java needed some tweaks for developer ergonomics, and I'm glad they finally introduced value types for example, but I now find that adding entire paradigms to a language is a bad idea.
In the case of Go, yes it needed generics, but in practice people don't use generics that often, so thankfully it won't affect most people's codebases that much. But there's people advocating for adding more functional programming paradigms and syntax like a function shorthand, which is really frowned upon by others, because new syntax and paradigms adding to the things you need to know and understand when reading Go.
Plus at the moment / the way the language is designed, FP constructs do not have mechanical sympathy and are far slower than their iterative counterparts.
Go is almost an anti-language in that sense, reluctantly accepting shiny lang features only after they’ve been proven to address major pain points. It’s almost more an “infrastructure deployment toolkit” than a language. Which strangely makes it extremely pleasurable to work with, at least for network-centric applications.
And let's be honest, Rust toolchain is pretty messed up too.
Want to cross-compile with go? Set the GOOS variable and you are done. On Rust you need to curl-sh rustup, switch to nightly, add new targets, add target to your cargo and cross fingers it works this week.
Maybe because a framework like ASP.NET or Spring that covers like 80+% of the enterprise needs hasn’t quite emerged? Or perhaps we just need to give it a decade or so.
There are still very few Go jobs in my country, most are either .NET, Java or PHP.
There is a reason why almost every good language is somewhat akin to C to this day, and maybe people started over to get rid of the noise.
Interesting. That's all anyone on my team ever used once it became available.
But, it highlights the point with Go. Working with Go for just a little while means I can easily read and work with nearly any Go project with a very short ramp up.
Could you provide some examples of this? From knowledge of the pipeline operator proposal[0], moving fast and breaking things isn't always a priority.
It goes without saying that Babel is an external collection of modules that don't fall under the TC39 umbrella, so they're able to iterate at a much greater cadence than the official specification (and you obviously need to explicitly opt-into using it.)
[0]: https://github.com/tc39/proposal-pipeline-operator/commit/da... (first commit; Nov 9, 2015, which is 8 years, 8 months, 24 days ago)
The moment I got my first compile error due to an unused variable and an unused import, made me realize Go is not a serious programming language.
Insofar I know it, I can imagine C/C++ caused some issues like that because it's hard to figure out whether an import is used, but an unused import does have a cost.
> Creeping dependencies can also affect the size of your project. During the development of Google’s Sawzall—a JIT’ed logs processing language—the authors discovered at various times that the main interpreter binary contained not just Sawzall’s JIT but also (unused) PostScript, Python, and JavaScript interpreters. Each time, the culprit turned out to be unused dependencies declared by some library Sawzall did depend on, combined with the fact that Google’s build system eliminated any manual effort needed to start using a new dependency.. This kind of error is the reason that the Go language makes importing an unused package a compile-time error.
If you want to use a private repository (let's say it's a private GitHub repository), then you either have to do it the bad way (setting up your own GOPROXY and setting it up securely, which implies also ensuring it's not leaking your source code elsewhere for "analytics purposes"), or the worse way (doing brittle text replacement using weird git config stuff).
Or the annoying way of using a vanity import, and host that package in your domain with HTTPS using a wildcard certificate. But that would require either (1) only allowing access through WireGuard and hoping whatever reverse proxy you use has a plugin for your DNS registry; or (2) letting your VPS provider terminate DNS (e.g. Hetzner load balancer), but filter by IP address in your VPS firewall settings ensuring your public address (IPV4 /32 or IPV6 /64) is always up-to-date in the firewall.
Or using `replace` in `go.mod`, but these don't work transitively so these only work on "root" projects (i.e. they are ignored in dependencies), so I don't think this really counts as a solution.
I would have liked some way to force SSH access for a specific package, instead of HTTPS. Like for example `go.mod` supporting a `require-private` to use instead of `require` (or whatever similarly convenient directive for `go.mod` that implies authenticated SSH access is required).
Or in other words, say I have a package `github.com/_company/project`, and it depends on `github.com/_company/dependency`. I want to be able to do:
git clone 'git@github.com:_company/project.git' 'project'
cd 'project'
go mod tidy # Should just work.
`go mod tidy` should just work without complaining about `github.com/_company/dependency` not existing (because it's a private repository only accessible through SSH).(EDIT: Still, I'm agreeing with the point that Go's tooling is better than most other things I've tried. My only complains are this one about being inconvenient to use private repositories, and also that by default it leaks package names to Google whenever you do `go mod tidy`.)
2) export GOPRIVATE='github.com/_company/*'
> On Rust you need to curl-sh rustup
Yes, but you do that once per computer, probably when you installed the compiler
> switch to nightly,
No
> add new targets,
Fair. But this is also one-time setup.
>add target to your cargo
Not sure what you're talking about here tbh
> and cross fingers it works this week.
Don't use the nightly compiler and you're good
But that's a whole different can of worms.
The more enterprisey software usually have lots of layers for organizational reasons, and go doesn't really fit there. So I don't think it will really be a hit in the enterprise.
yes there are orm solutions and DI frameworks and all that, but they always feel like they don't belong in the language.
(Also, java and .net and php are much older and have much bigger enterprisey ecosystem.)
I have seen go replacing the php stack though, and in some way the "original" python stack - but python now has ML.
The ridiculous number of layers in Java or C# are more of a skill and guidance issue than anything else. Older languages don’t always mean over-attempted-abstraction (think C, for example).
(Disclaimer: I don't agree with HTMX rendering HTML chunks on the backend side, and I think that APIs should be HTTP-cacheable and use REST/JSON)
Currently I am trying to get better at using Go with WebAssembly for the frontend. I love to use the webview/webview bindings to build local GUIs, but the need for redundant code in JavaScript for client data transfers and input data validation are annoying me a bit much.
I am trying to find out a paradigm that could benefit from the strength of JSON marshalling, with the idea that you can map routes to structs, for example, and where a unified "Validate() (bool, error)" method as an interface is enough to use the same structs on both the frontend and backend, for both serialization and validation/sanitization.
Having said that, I think that what's missing the most in go right now is a good UI framework for the web, but it's hard to find a paradigm that fits nicely into the language while also being able to handle dynamic data/refreshes/render loops without getting too bloated too quickly.
Rendering html on the server does not make it not cacheable.
The vast majority of people do not need graphql or shift their compute to the client with a junk react app with adhoc json endpoints everywhere.
I mean there's a slow shift, I keep hearing of "rewriting a Java codebase to Go", but it'll be a slow process. And especially the bigger projects that represent 30 years of Java development will and should be reluctant to start rewriting things.
The backwards compatibility promise:
Programming languages more than almost any other type of project end up swamped with thousands of competing requests to implement mutually incompatible features. Some languages do better than others at saying no, and those languages tend to be the ones that achieve widespread adoption.
Unfortunately that’s not at all true - Go is a real outlier here. If it were true, we’d all be writing C instead of C++, Lua instead of Python and ES5 instead of TypeScript.
Hm. Wasn't (the lack of) generics pretty drama filled? Especially the way they fought against it for so long.
Is that true? In what sense? I was under the impression the editions took care of that.
That said, I’ve also worked with JSF and PrimeFaces project and the ones I’ve seen have been more burdensome from a maintenance perspective and also more buggy than most SPAs that I’ve worked with.
I’ve also seen large monoliths where the tight coupling slows updates down a whole bunch, as opposed to the presentation being in a SPA that’s separate from an API that can be more limited in its scope (nothing wrong with using ASP.NET and Spring for just an API).
Heck, I’ve migrated a SPA from the now defunct AngularJS to Vue and it felt better than having a legacy project that’s stuck on an old version of Spring and PrimeFaces because there’s so many moving parts that when you try to update anything, everything breaks.
Plus, turning a SPA into a PWA is a fairly pleasant experience. I don’t think most folks need GraphQL though, especially when we can barely do RESTful API correctly and not even all places use OpenAPI specs and tooling, making client code impossible to generate (even SOAP did a better job in that particular regard with how widespread WSDL was).
`go vet` is part of Go toolchain so the designers very much understand and acknowledge that code can have issues that are not always errors.
The distinction they made is very simple: an error is something that is always wrong and a vet warnings is something that is possibly wrong but not always.
They made a judgement call to split the responsibility: compiler only reports errors, other tools, including `go vet`, can tell you about other issues.
For example: passing a large struct by value to a function is potentially a performance problem but it's also correct code.
If you ever tried to compile C++ code with different compilers you would know why it's a wise decision.
The set of warnings is vast and not standardized so you take C++ source from project. It compiles for them but doesn't compile for you because you use different compiler or enabled different set of warnings. At which point you either try to get the other project to "fix" something that isn't an issue for them or you do stupid, pointless, time consuming work adjusting your build system.
The same would happen in Go and it would be a reusability killer. You use some library in your program but it doesn't compile because you decided to use more strict set of flags.
Lack of warnings switches also simplifies the toolchain. In go it's just `go build` and it works.
In C++ you have to write some kind of makefile because everyone executes `cc` with different set of flags.
Code review happens in public, not on GitHub but on Gerrit. The main issue tracker is public, on GitHub. Proposals are largely handled on the issue tracker. There are public mailing lists, etc.
Surely, there are face to face private meetings. And there are likely also private issue trackers, mailing lists, and etc. And, yes, sometimes, a seemingly arbitrary decision pops up, that was clearly discussed elsewhere.
But these comments seem to come from people who never even tried to contribute, or deal with the process.
I've done docs fixes as a total newb, had to convince the Windows maintainer to let me fix a Windows issue (that a year later produced flaky tests, which I fixed), made and got a proposal accepted, have a project in the linkname hall-of-shame, which led to another successful proposal to open up APIs (which then failed tests on some platforms, which I fixed).
All with little drama, pure engineering.
`match` also breaks fundamental Python principles [2] and interacts badly with the language's lack of block scope:
>>> a, b = 1, 2
>>> match a:
... case b: pass
...
>>> a, b
(1, 1)
Not to mention that it also required large changes to the CPython implementation, including an entirely new parser(!) - which means other implementations may never support it [3]. Clearly `match` doesn't fill a gap in a coherent design for Python. It seems to have been added due to a combination of FOMO and/or resume-driven development.Another example is async-await - while the concept is fine (although I think stackful coroutines are a better fit for a high-level language), the syntax is just copy-pasted from other languages [4]. There seems to have been little thought as to why C# etc chose that syntax (to allow `async` and `await` to be contextual keywords), nor how `async def` contradicts existing Python syntax for generators.
[0] https://peps.python.org/pep-0635/#motivation
[1] http://canonical.org/%7Ekragen/isinstance/
[2] https://x.com/brandon_rhodes/status/1360226108399099909
[3] https://github.com/micropython/micropython/issues/8507
[4] https://peps.python.org/pep-0492/#why-async-and-await-keywor...
> Essentially the language would stop evolving. I worry that that would make Python become the next legacy language rather than the language that everyone wants to use.
https://discuss.python.org/t/pep-8012-frequently-asked-quest...
Structure of code often reflects structure of your company.
The code is often maze of layers because the company is a maze of sub-committees. Java/C# fits more neatly in there.
Although with Go, what can happen is that there is a maze of microservices. Maybe that's not that much better.
Enterprise Architects will do their beloved architectures with whatever languages are the tool of the day.
I'm definitely considering the same, and you're right - it's not C++ itself that appeals to me at all, it's the libraries. I'm not sure what C libraries I'd use for collections (instead of the STL and Abseil [0]), or in lieu of CLI11 [1] or Dear ImGui [2].
[0] https://abseil.io/about/design/swisstables
If you don't agree with the available languages, make it better. That's the power of open source :)
Who gave him control over what sees widespread adoption?