Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Hacking Go's runtime with generics (dolthub.com)
69 points by awmarthur on Dec 21, 2022 | hide | past | favorite | 109 comments


Honest question: isn't Go a bit of a weird choice for a database given the GC? Why not C/C++/Rust?


C/C++/Rust - will not solve anything magically. Anyway you will need to implement some kind of memory management for DB.

Go GC creates problems and they are non-trivial (as all memory management) but it's not so twisted as in JVM.

Examples:

- DGraph: migrated from RocksDB (C++) to Badger (pure go, developed themselves, based on jemalloc)

- CocroachDB - pure go for storage engine

- go 1.20 proposed feature: package `arena` for region-based memory management


If you like/trust dbdb.io, most databases are written in C++ or Java. C# and Go are also high on the list.

https://dbdb.io/stats


Why can't a database be written in a garbage collected language?


I believe you usually want as much control of memory management as possible as it can be a great place for finding performance improvements and also help in delivering very consistent performance. Automatic memory management is a great aid in reduction of the complexity you have to deal with, but you presumably want to deal with that completely in the context of a database.

Seems like this: https://www.cockroachlabs.com/blog/why-go-was-the-right-choi... and more specifically this: https://www.cockroachlabs.com/community/tech-talks/challenge... would be good to explore for how cockroach has made it work w/ Go+GC.


> I believe you usually want as much control of memory management as possible as it can be a great place for finding performance improvements and also help in delivering very consistent performance.

Sure, but premature optimization is the root of all evil right? Get something functional, then make it performant by handling the problematic cases. GC doesn't prevent this progression, it's just a significant help to getting something functional.

GC can sometimes lead you into designs that can't be optimized without a change in abstraction, but it's not at all obvious that you would have landed on the right abstraction if you didn't have the GC to begin with anyway. I think getting something working as fast as possible lets you gather the data you need to make a performant design, and having to handle all of that complexity up front without a GC just delays the data gathering stage.


If you end up being wrong you will either have to fight the language or completely rewrite it in another.

It is not premature optimization but an intentional design choice, and a valid one to make.


> If you end up being wrong you will either have to fight the language or completely rewrite it in another.

This is mostly a myth.


> premature optimization is the root of all evil right?

Making sure they're aren't a bunch of alloc's or GC spent in the hot path of a high performance library is hardly a premature optimization.

If you're tackling problems in DB land changes are you already have a fairly clear picture of what needs to happen and have a list of shortcomings you're trying to avoid. Memory layout, buffers, wals, etc are all things that should be accounted for upfront.


> Making sure they're aren't a bunch of alloc's or GC spent in the hot path of a high performance library is hardly a premature optimization.

You often don't know the what the hot paths are.


And if the GC ever starts slowing you down, just run a profiler and eliminate the allocations. It's usually as simple as replacing a dependency or using sync.Pool in the hot path.


You can allocate memory manually in Go and manage it yourself using Go's `unsafe` package, so there's an escape route once Go's GC became a limiting factor. Here's a blog post about it in the context of Dgraph: https://dgraph.io/blog/post/manual-memory-management-golang-...


The real issue with go is (or was, I haven't messed with it for a few years) its un-optimized goroutine scheduler that makes channels slow if you start using them a lot.


Yes, refactoring from channels to atomic package can easily give 10x speedup. Sometimes we have to communicate by sharing memory :)


Ease of use


ELI5. How is maphash different from just using map?

I am surely missing something. I thought the builtin map used hashing too?


The maphash package from the blog post provides routines that call into Go's runtime to hash arbitrary types.

The maphash package in the standard library (hash/maphash) provides routines that hash string and []byte.

The builtin map type is a hash table.


Ahh I somehow misread the post and thought it’s a generic map that uses hash table.

I should get some sleep, thanks


Maphash is a library for computing hashes of arbitrary types in Go, not a map data structure.


Maphash is an (non-cryptographic-secure) hash function, like CRC32 / CRC64 / XXH3-64 and others, so it turns data in an (almost) uniq uint64.

The main difference is, it is an hardware accelerated & optimized compiler function, now exposed via the new maphash package in stdlib.

And it is fast. Faster than the former performance leader xxh3(avx2/avx512).

Try maphash yourself (example data dedupliction) https://news.ycombinator.com/item?id=34091206


So the reinvented wheel (golang) is now starting to miss / reinvent Java's .hashCode() or an alternative to it?


Sort of, except the way Java did it is awkward because they put a method on Object instead of making it an interface. It's not clear from the API what's really usable as a map key.

I'm not sure making all comparable objects in Go usable as map keys is a good idea either.


> I'm not sure making all comparable objects in Go usable as map keys is a good idea either.

Was a good idea since, it's part of the spec-definition of Go:

> A map is an unordered group of elements of one type, called the element type, indexed by a set of unique keys of another type, called the key type. [...] The comparison operators == and != must be fully defined for operands of the key type

TFA is merely reusing that.


[flagged]


Please don't take HN threads into programming language flamewar. It's one of the last things we need here, and it's easily avoidable.

https://news.ycombinator.com/newsguidelines.html


To be fair, a lot of those concepts were invented, at very least popularized, by the members of the Go team 30+ years ago. Go is their chance to carefully bundle those ideas together, not just throw every random idea they can think of into a language and end up with a big ball of mud like so many others want to do. There are already plenty of ball of mud languages, if that's what you're looking for.


> To be fair, a lot of those concepts were invented, at very least popularized, by the members of the Go team 30+ years ago.

Er... no? Not even remotely?


Very much so.


You'd be hard pressed to name anything in IT that wasn't "discovered" in the 60s-80s but implemented/re-implemented recently


We're not talking bleeding edge CS topics here mate, we're talking "hashability is a useful property because hashmaps", that was standard >25 years ago.

Java had hashCode in 1.0, GvR added __hash__ to Python in March 1993 and shipped it in 0.9.9.

Hash maps are 69 years old (nice). Bespoke key types (and thus the requirement for user-defined hash functions) is probably the more recent of the two.


So you don't understand what's happening here. They are not "hashing a structure", they are digging into internal implementation to reuse code that runtime uses to hash the structure.

> Java had hashCode in 1.0, GvR added __hash__ to Python in March 1993 and shipped it in 0.9.9.

is not doing that. It is just providing an interface that happens to be filled for builtin types

Also Go is not object oriented language and types don't have default set of methods returning things so having type.hash() like Java or Python would make no sense. Whether that's a good or bad call is another discussion but writing generic Hash[T] is few lines of code and would be just encoding/gob into hash of your choosing.

There is a case for providing that in function doing what the dolt guys are doing but that would be "just" optimization.


> So you don't understand what's happening here. They are not "hashing a structure", they are digging into internal implementation to reuse code that runtime uses to hash the structure.

Because Go does not expose the builtin hash function.

> is not doing that.

It's doing that without the feature existing.

> Also Go is not object oriented language

Which is not actually relevant, it clearly knows about "comparable" (which it also considers to mean "hashable"). It just refuses to expose that information.

> so having type.hash() like Java or Python would make no sense.

Are you wilfully picking at the tree's bark in order to avoid considering the forest for a single second?

> Whether that's a good or bad call is another discussion but writing generic Hash[T] is few lines of code and would be just encoding/gob into hash of your choosing.

And lose the benefit of the way the entire ecosystem works.

On the plus side, it would let you have keys with bespoke equality and hashing semantics, but that's clearly not what TFA is looking for.

It also can't be combined with go's own hashable because you can't involve either "comparable" or an interface with methods in a union, so there is no way to accept a "comparable|Hash" in order to leverage both.

And obviously by doing so you'd open the door to them being inconsistent. Which is also the point of using Go's own concept of hashability.


I do not understand the appeal of go.

> The proposal argues that Golang developers are forced to work around language when writing hash-based data structures like Tries or concurrent hash maps. Developers who want an efficient hash-based data structure have only the builtin map to choose from. When this issue was originally created in 2017, Golang didn't have generics

And then the author goes to tell us about how this is not a stable solution.

I get wanting to solve a problem, but at what point into fighting the language, to accomplish something simple, do you take a step back and just pick a better one?


The appeal of Go:

- A pretty simple, if not very expressive, language (it's anti-Perl, and seems simpler than JS); you can learn it down to a reasonably productive level in a weekend. (I did.)

- A memory-safe language (like Java) with good performance (like Java) without the need to install any runtime, and the ability to ship as a single binary (unlike Java).

- A reasonably good and ergonomic concurrency approach (like JS, unlike Java), based around channels, not futures, and able to embrace multicore parallelism (unlike JS, like Java, and somehow like Erlang).

- Highly opinionated, well-crafted built-in data structures (like Python), and a general approach discouraging you from rolling your own.

- Good cross-platform support; fast compilation.

That is, it's a language that works well in a case where most of your team is junior devs, and you write some kind of a network server. The devs are forced to follow simple, if repetitive and wordy, patterns, and are limited in their ability to raise creative mayhem in the code base, all while writing reasonably performant, concurrency-friendly code that's a piece of cake to deploy. Combined with some overview from more senior folks, this should work reasonably well (and apparently that's what how it works at Google).

No. it's not a joy to use, it has warts (or, rather, deliberate compromises) in many areas, it requires boilerplate which pushes the user towards copy-paste programming, etc. If you can afford to not use it, don't, but sometimes it's the easiest tool for a job, much like, well, PHP.


> ship as a single binary (unlike Java).

Possible with GraalVM. Has been possible if you were willing to pay long before that. GraalVM produces statically linked binaries with only one external dependency — zlib, which is preinstalled pretty much everywhere. Startup time is measured in milliseconds.

I recently built a mid-size REST backend with quarkus — it ships as a single binary with size comparable to what I'd expect to see if it was written in Go, and starts in about 200 ms (from executing the command to when it's ready to serve its first request).

Having written code in both, I hope GraalVM buries Go in the long term, but in our hype-driven culture it's unlikely.

https://quarkus.io/guides/building-native-image#configuring-...

https://github.com/oracle/graal

> A reasonably good and ergonomic concurrency approach (like JS, unlike Java)

This is also very close to being solved.


I actually find go a joy to use, I dunno.

I like statically typed languages, and go makes defining and using types so simple and straightforward that it feels like you get a lot of the benefits of dynamic typing without the headaches.


I love statically-typed languages!

What bothers me in Go is mostly the control flow around `result, err := foo(); if err != nil { return err };`, and still non-genericized standard library. But after 1.18 I started to look at Go as a potentially good language, in areas where using Rust is too cumbersome, and using Typescript or Java or Kotlin is also inappropriate.


What I do not understand is why on every article about Go someone needs to extol their dislike of Go. If you don't understand its appeal, then either you should give it a (serious) try and see if you like it, or if you are unable to bring yourself to do that, just use those better (according to your opinion) languages.


It's like a hackernews meme at this point, complete with "I used Go before and my life was a meaningless void and then Rust came into my life and now I see the light." It's all so predictable and boring and derails nearly every Go thread.


The hackernews meme a few years ago was about how Go could do no wrong, and any perceived deficiencies was it due to being opinionated. Maybe this is a backlash?


The concept of "opinionated" itself is a meme.


Unfortunely that isn't always a choice that we can influence, project => language, and in some cases that implies using a language that we dislike, regardless of how we feel about it.

One can go job hoping as alternative, but then good luck jumping jobs everytime one has to deal with stuff we dislike.


I hopped jobs to go from using Go to Rust, I was sad and bored, now I'm happy and energized. Always going to be things you dislike for sure, but life's to short to be using a language that's making you miserable.


Which is true, assuming the job market is great on the area, which even on IT isn't the case.

Thankfully I seldom have to deal with Go anyway.


True, but can you really work day by day in a language and still not understand its appeal? I mean, not like it, but at least understand why others might choose to use it? And, if you really can't bring yourself to see the positive sides of a language you have to use (and any mainstream language has to have positive sides, otherwise it wouldn't be mainstream), maybe it's really time to consider switching jobs...


I see Go's appeal as a better C for userspace code, and the language is quite nice had it been released during the days Oberon and Limbo mattered in the mid-1990's.

As post 2000 language, its design isn't that appealing.

The language would have been as mainstream as Oberon and Limbo were, if the authors weren't working at Google.


> True, but can you really work day by day in a language and still not understand its appeal?

Yes. I have been working with Go for close to a year now, and I still don't get why we use it, if not for the inertia of times past – and I still don't get why it was chosen in the first place.

If we wanted a fast, down to the metal language, Rust would IMHO be better.

If we preferred a higher-level language with a Gc, Java/Kotlin/C# would be, IMHO, much better.

And both paths offer the same level of tooling, so it's still a mystery to me.


>If we preferred a higher-level language with a Gc, Java/Kotlin/C# would be, IMHO, much better.

Writing code in Java\Kotlin requires quite some investment into the language and tooling (at least that's my Java impression).

With Go - you can start getting the job done from day one most of the time. Some parts of Go may be harder than the others, even challenging maybe, but not as hard as Java.

Lack of OOP (at least in Java's traditional scence) also helps quite a lot (but that depends on project of course)


To be honest, I think that go packaging is ghastly (just accessing dependencies in private repos requires changing global git settings, which is an abomination), but I can see how Java can be very heavy on that.

However, I would not weight too much the time-to-first-makefile of a language if a project is supposed to live for years.


>just accessing dependencies in private repos requires changing global git settings, which is an abomination

Just put a .netrc file in your homefolder with your username + token and use GOPRIVATE env variable. No need to change any git settings.

After go modules became mainsream most go packaging issues where out of question, imo. At least for me the 'private repo packages' was the only issue.

I'm pretty sure that there are millions of js projects out there, many of them been there for years and will be there for many years to come, all despite npm and js packaging issues in general...

At the same time Go provides enough stdlib to forget about dependencies completely if you are afraid that use of some of them (or packaging system in general) may result in some negative scenario.

This is where Go shines: it can offer enough to be powerfull without becoming java. But without a doubt Go has many things to improve too.


> Just put a .netrc file in your homefolder with your username + token

Lol yes, let's just put sensitive information in plain text in my home folder and change the machine-wide configuration, because Go guys decided that if it worked in 1970, it is good enough for today.

> the 'private repo packages' was the only issue.

That's quite a big one for a language targeting companies.

> I'm pretty sure that there are millions of js projects out there

Sure, if your gauge is the JS ecosystem...

> At the same time Go provides enough stdlib to forget about dependencies completely

Go stdlib is decent, that's it. It does not even has basic data types such as sets (no, map keys are not a decent replacement for a set), queues or stacks.


>Lol yes, let's just put sensitive information in plain text in my home folder and change the machine-wide configuration, because Go guys decided that if it worked in 1970, it is good enough for today.

That't just your login and a token that gives read-only access to some repo. Hardly an issue imo. At least if this is your work PC. (also - while home folers is the default the file can be places somewhere else)

>Sure, if your gauge is the JS ecosystem...

Why not? Because some guys on HN is salty about it? JS is extremely popular and widespread. Much better gauge than something being used by a few guys.

>It does not even has basic data types such as sets (no, map keys are not a decent replacement for a set), queues or stacks.

I'd argue that channels are your queues. Maybe sets and stacks will be added now that generics are part of the language.


Huh, the one reason that I'd wish most languages would die and we picked like... 5 is that seemingly every time I hit a project I'd want to hack upon it's in language I don't know...


Hell, just scroll down in this thread to see the clowns. Maybe envy that their favourite toy/niche language didn't get popular instead ?

Like, there is plenty of flaws clear to see in Go but it does some jobs well and that's all that's needed to be useful language.


This is an article about an idiosyncratic and fairly interesting approach to writing a fast generic striped map in Golang. Responding to it with a language war appeal is arson; maybe not the "pouring gasoline onto the building" kind of arson, but certainly the "tossing your lit cigarette into the dried up pile of brush" kind. Almost the entire thread on this story has been consumed by a litigation of whether Go is good or not.

If you don't like Go (or Rust or Haskell or Elixir or Ruby), that's fine. Just don't comment.


I hate Go, but there is no solid alternative for what I do. Documentation quality. Compiler performance. Library support. Easy packaging. Easy language. Consistent cross platform tooling. Easy concurrency. Good for web apps and CLI tools. Reasonably refactorable.

Note I say easy and not good, or simple.

Rust, Haskell, JavaScript, all get caught up on some aspect or another for me.


C# may fit your needs, depending on what you consider a simple language and easy concurrency. The language doesn’t feature any hard to understand concepts. Concurrency is very good, but only async has built in syntax sugar (I believe go has syntax sugar for channels or something?).

The executables may be a bit larger (I’m guessing).


C# is far from simple. It used to be be but lately (in that last ~5 year) they have been adding a lot to a point it has become hard to follow the changes, and hard to read modern C#.

When I was C# developer I welcome the addition of FP like feature, but now imho the lang have become very cluttered. GO lang is in another level of simplicity and it is not comparable with C#.


Just wait when Go gets 20 years of existence and enterprise use beyond devops.


> Just wait when Go gets 20 years of existence and enterprise use beyond devops.

C# is really reliable language, great tooling and documentation but it does not change the fact that is cluttered and no longer simple (which was the point of my comment).

Also I can't see golang going to the same direction, by design go is a lot simpler.


I had my share of reviewing and working with C#. There are certainly ways where developers can be "clever" with it and it becomes confusing and unworkable mess. Haven't seen that with Go.


You obviously don't hate go.

Everything you listed help programmer to keep own sanity.

It's all compromises but they're mostly reasonable compromises.


I've been writing software for 20 years. About half that in Go.

Whenever I see someone say it's a bad language because X, I seriously wonder if the asker just writes terrible code, or if there's whole swaths of domains I've not encountered. Or maybe a little of both.

I've never once been stumped by a lack of generics, for example, despite how many people claim it's unusable without them.


No it's mostly just the blub paradox. You don't feel the pain because you didn't use some features/techniques of other languages that don't exist in Go.

It's the same everyone. I, for example, never felt I was missing something until I learned about type providers. Now that I don't work in a language that supports them, I hate it. If I had never learned about them, I would probably never miss em.


He didn't express a lack of pain, just that he was never in a situation where he was stumped by not having them. Generics aren't exactly magic. They can improve code, but you can live without them if you really have to.

Although I think you are on to something per the original question about the appeal of Go. For all its faults, Go also gets a lot of things very right that aren't obvious until you have gained the necessary level of familiarity.

Once you rise above 'blub', it is indeed hard to go back. While I spend most of my days in other languages full of all kinds of fanciful features, I did a short stint on a Go project and now especially hate not having blocking functions everywhere (async/await is one of those fanciful features I have to deal with) and sensible error handling.


> He didn't express a lack of pain, just that he was never in a situation where he was stumped by not having them.

I mean, isn't that the same thing? You don't know you are "stumped" if you never experienced it. That's what I mean by "feeling the pain".

> Generics aren't exactly magic. They can improve code, but you can live without them if you really have to.

Of course - that's true for essentially any language feature. We can all use assembly if we have to, but I think that's missing the point of why OP asked.

> Although I think you are on to something per the original question about the appeal of Go. For all its faults, Go also gets a lot of things very right that aren't obvious until you have gained the necessary level of familiarity.

Sure, I mean: if you always used a language with an unergonomic and non-integreated builtsystem, you probably won't feel the pain or won't feel it as much as when coming from golang. That would be blub the other way around. Worse: the more languages (that are actually different) you have used, the more unhappy you are with every single existing language.


> I mean, isn't that the same thing?

Not at all. The claim about not being stumped was made in response to criticism that Go is unusable without generics. Said criticism was probably made up, but I guess it was still interesting enough to garner the response that ultimately brought us here.

> That would be blub the other way around.

Seems like blub the same way around. Indeed, the blub paradox itself is paradoxical.

> the more languages (that are actually different) you have used, the more unhappy you are with every single existing language.

And the more you really appreciate just what Go has done by taking an engineering approach and not an academic approach.


Plenty of software has been written on languages without generics, but they have the excuse of coming up before generics were a common feature in mainstream languages.

At least that has been finally fixed.


Generics were never required, just their lack was annoying and their presence makes some things just cleaner and easier

For example I deal in ops stuff so pretty common task is "here are desired and current set, generate list of add/delete operations to get from one state to another".

I wrote iteration of that function a bunch of times pre-generics, eventually being just copy-paste-change-types but now I can just write [1] one that compares a slice of types and returns the elements present in left or right and [2] another that can do similar difference on disparate types via conversion function.

Then there is a whole slew of map/reduce and math stuff that now can just have `Map` or `Max` function without worrying about types. Hell I can "just" write "parse all the slice elements in parallel, keeping order [3] once and never worry about it. That's also code that I wrote more than once before generics

* [1] https://github.com/XANi/goneric/blob/master/slice.go#L77

* [2] https://github.com/XANi/goneric/blob/master/slice.go#L106

* [3] https://github.com/XANi/goneric/blob/master/parallel.go#L15


On one hand, the bar for things to be called bad has now dropped pretty low. Being not as excellent as other thing, or not being excellent throughout is enough.

But I think the actual hate isn't coming from Go technical shortcomings. It's language authors and community attitude towards people asking for obvious QoL improvements.

Generics are a bad enough example of community for years tactfully flipping off everyone asking for them and then, hey, here they are and the sky doesn't seem to be falling. But it's not the only example. Just a couple days ago I was researching if there's a way to somehow build struct tags from constants or use interpolation and sure enough, there's an old bug tracker suggestion entry that got a two sentence "won't do" reply with zero reasoning and a bunch of following entries just marked as duplicate and closed without reply at all. This happens a lot. And people don't appreciate it.


> I've never once been stumped by a lack of generics

Heve you never written a stack structure (since Go doesn't include one)? Never used a min/max function between numbers (go doesn't either)?


Those are not show-stoppers, just annoyances.

Generics make it oh so much nicer to do some stuff but lack of them wasn't exactly something that I missed, just that I wished some libraries had for the cases you mentioned (generic map/reduce/math/etc.)


I have, maybe a couple of times. Never missed generics.


> I get wanting to solve a problem, but at what point into fighting the language, to accomplish something simple, do you take a step back and just pick a better one?

My guess is that they got excited at the chance of doing something mildly interesting, beyond the mind numbing "regular" go.


>I get wanting to solve a problem, but at what point into fighting the language, to accomplish something simple, do you take a step back and just pick a better one?

..coz they already have code in it ? Coz they are happy with remaining 99% of the language ? It's not hard to figure out cmon.

If people dropped language at slight inconvenience we'd be out of languages


> I do not understand the appeal of go.

I am an amateur dev developer and used to use untyped languages (Python and JS, mostly).

At some point Python was annoying in docker environments (especially for APIs) and I gave a try to Go. Initially I hated it, then learned to like it more and now I kinda like it.

- typed (this is a game changer)

- compiles to a single self-contained binary (easy with Docker)

- great for APIs without the worries of gunicorn and whatnot

I also discovered TypeScript to help with JS.

So the forst one would be "typed language". I have Python for the rest ("the 2nd best language for any task") and since I am an amateur dev, I do not have the time to dig into many languages to find the pearl.


I think he didn't mean tries which don't generally need hashing but was trying to implement a lock-free map based on Concurrent Hash-Array Mapped Tries.

I had done that myself as an exercise a few years back and had to extract the hash function from the runtime that is used for maps.

In any case, the performance was terrible and code brittle. (lack of sumtypes).

Since then, I've learnt to not bother too much and just use the builtin maps. Never had an issue for my use-cases.


(OP) I'm mostly interesting in a fast hash for writing a generic, concurrent hash map.

The reference to Tries came from the original issue in the Golang repo about possible uses for a standard library hash function: https://github.com/golang/go/issues/21195

And you're right, the Trie implementation linked there was indeed a Hash-Array Mapped Tried: https://pkg.go.dev/github.com/lleo/go-hamt-key#Key


I mean it's a good exercise I guess if you want to flex your language knowledge, but it goes against the mindset of Go to actually use it in production. Said mindset being don't overcomplicate things.

One doesn't need Go to not overcomplicate things either. I wanted to advocate in favor of Go for a long time, and still do recommend it, but it's the mindset that is more important.


What I fear most is starting to absorb the "reserved for language designers, not for me" mindset. Stubbornly bending the language to serve you is a much healthier attitude for anyone who wants to maintain his expertise.


>I get wanting to solve a problem, but at what point into fighting the language, to accomplish something simple, do you take a step back and just pick a better one?

What makes you think they haven't tried what you think are "better ones" and moved away because they had more problems to fight the language/ecosystem about with those?


> pick a better one?

Such as?


I'm hoping Kotlin + GraalVM Native Image can fit the niche of golang.


No VM language can fit the niche of go.


Why not?


Kotlin might fit the Java niche, if you trust someone that sells IDEs to make a language.

Go's niche includes being native. If you discard that, then virtually anything that is "easy" could fit it.


Then use an AOT compiler, plenty of those for JVM since 2000.

While one can excuse themselves that they were commercial, GraalVM native image, and OpenJ9 offer free beer alternatives.


I looked into using Graal one time. Many of the dependencies I used were not compatible. I also encounter weird bugs with any of the OpenJ* alternatives. In Go, everything just works.


The JVM proponents are usually being dishonest when they compare Java/Kotlin AOT compilation to Go. They know very well that a large number of popular libraries either outright don't work or have severe restrictions when using AOT. It's also common to run into bugs since Graal is relatively new and only a miniscule percentage of the Java community uses it. It's not even remotely close to Go where everything can be assumed to work.


No we aren't, because there have been commercial compilers since around 2000, with Excelsior JET being one of the first ones, sadly out of business.

However, PTC and Aicas are still in business,

https://www.ptc.com/en/products/developer-tools/perc

https://www.aicas.com/wp/products-services/jamaicavm/

IBM's commercial one is now freely available on OpenJ9,

https://www.eclipse.org/openj9/docs/xaot/

Finally, if you are using a modern Android phone, an AOT compiler is in the box since Android 5, and it was modified into a mixed JIT with AOT compilation on rest since Android 7.

GraalVM happens to be the evolution of MaximeVM, and certainly not the only game in town.


I was just reading that Spring 6 introduces Ahead-Of-Time compilation, enabling first-class support for GraalVM native images with Spring Boot 3. So hopefully the situation is improving.


You're totally missing the point of the niche in question.


Indeed, compiling to native code is missing the question apparently.

Or is the niche not being able to understand JVM languages, that expect developers to have PhD skill levels, as per Rob Pike's own words?


So they're missing the niche of "being native", by suggesting... using an AOT (= native) JVM compiler? Meaning making essentially every JVM language native?


> Kotlin might fit the Java niche, if you trust someone that sells IDEs to make a language.

They would at least know how to make a language that's not a pain in the ass to analyse, which is probably in its favour.


Yea - but that's offered by all modern languages, and they're not tied to one particular IDE since LSP took off.


> that's offered by all modern languages

I see you've yet to meet Scala.

> they're not tied to one particular IDE since LSP took off.

There's at least one language server for Kotlin.

I'm not even a interested in (let alone a user of) Kotlin, but you seem to have a very not-objective view of it for some reason.


Are you saying Scala has bad code analysis? I recall it being as good as Java's. Anyway, that's just a matter of defining "modern languages" then.

> There's at least one language server for Kotlin.

I didn't say there is none, I said that any modern language has one. An IDE is not a selling point anymore, in my humble opinion.

> you seem to have a very not-objective view of it for some reason

I just think that shoehorning Kotlin into "the go niche" is absurd , and that the "good code analysis" argument is moot.


> I just think that shoehorning Kotlin into "the go niche" is absurd

That's what you say, but you don't really tell us why.


It's not my burden of proof. If you think something like compiling kotlin instead of running a JVM is akin to compiling with go tooling, then at this point anything that somehow compiles to native (and beyond) is in the "go niche".


> It's not my burden of proof.

You're the one asserting that it's unsuitable. So it very much is.

> If you think something like compiling kotlin instead of running a JVM is akin to compiling with go tooling, then at this point anything that somehow compiles to native (and beyond) is in the "go niche".

I don't know about the other commenters, but that's literally the only criteria you've deigned offer so far, aside from some sort of conspiratorial implications.


So if I say <any language> is in go's niche, it's your burden to disprove it?

Look, this is getting ridiculous. Go offers easy+fast tooling out of the box. Any JVM language, compiled or not, will never be anywhere NEAR go's tooling in those terms. The extra compilation layer just makes it actually much worse.

And I don't even find go particularly appealing.


My choices would be:

- Elixir

- Rust

- Clojure

- Crystal

In that order.


Are you an expert in all those languages? To me these are the exotic languages which one gets inspired from when reading the stackoverflow survey, but there is hardly any one person I know who has mastered even half of those.


Once you’ve learnt a few languages, learning more becomes easy. Elixir, Rust and Clojure are all reasonably widely used. And I would note: somewhat similar to each other.


I don't consider myself an expert at anything, but yes, I use these languages on a daily to weekly basis at work. We had some Go code, but replaced it with Elixir.

EDIT: I'd also like to add that Elixir and Rust aren't "exotic." Crystal may be, but it's basically just compiled/typed Ruby.

I've been using Elixir professionally for seven years across multiple companies:

1. Divvy.

2. GoSkip.

3. Podium.

4. Actiphy.


If you allow me, my take on the list:

* Clojure is a really nice and simple language, but the tooling and documentation comes nowhere near go, also it uses JVM, which would already disquilify as go replacement.

* Rust is nice (or even better in a lot points) but a lot harder. Concurrency in go is just lot easier.

* Elixir, I agree, although I don't have much experience of the language.

* Crystal, not clue about this lang xD.


There are AOT options for JVM, just need to learn how to use them.


Elixir is wonderful, but its deployment story is much more complicated than Go's or Rust's.


I don't think Elixir's deployment story is difficult. It doesn't result in a single executable, like Go compiles to, but it's easy to deploy Elixir apps and the compiled package contains everything necessary to run (meaning you don't have to install Elixir, Erlang, etc. manually in production).

The biggest benefits of Elixir over Go for me are:

1. Pattern matching.

2. Easier concurrency (with less resource usage).

3. Piping.

4. Easy to hire and train Ruby or Crystal developers.

5. Phoenix is an outstanding web framework for Elixir.

6. Excellent tooling.

7. Supervision trees.

8. Actor model.

9. Elixir's concurrency is done in private memory, whereas Go uses public memory.

EDIT: Fixed formatting.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: