7 ms·
Can someone explain what Erlang offers that Go does not? Both have great support for concurrency, but Go has type checking and a more familiar syntax.
by gautamcgoel 6y ago
Can someone explain what Erlang offers that Go does not? Both have great support for concurrency, but Go has type checking and a more familiar syntax.
- emit_time 6y agoDoesn’t erlang have a REPL, allows you to do live deployments. Individual processes crashing doesn’t bring everything down, you can tell it how to handle those. Dynamic typing. Functional programming. Concise syntax, with “let it fail” mentality.
- epidemian 6y agoThere's this talk, The Sould of Erlang and Elixir, that opened my eyes to what makes this platform great: https://youtu.be/JvBT4XBdoUE https://youtu.be/JvBT4XBdoUE It's not so much about what Erlang, as a language, "offers that Go does not". It's about the BEAM VM that runs it that makes all the difference. I very much recommend watching the talk if you're interested in the topic :)
- coder543 6y agoI watched that talk just now, and it was basically a retelling of everything I really like about Go. Except, Go is statically typed, and a lot faster than BEAM in benchmarks that I've seen. Go is also a very "normal" language, so it's usually easy to onboard developers into it, no matter what their background is. JetBrains GoLand makes the IDE experience essentially impeccable. I can refactor code with a few clicks, and GoLand precisely updates all references thanks to the static type system. Go can run massive numbers of Goroutines on a single system, and it preemptively timeslices individual Goroutines, so I'm never worried about any single task preventing other tasks from making progress, which was like 75% of that talk. Go has a fantastic production runtime debuggability story, which was the other 25% of that talk. Go's pprof support feels magical: https://golang.org/pkg/net/http/pprof/ https://golang.org/pkg/net/http/pprof/ You can connect to running systems and see flamegraphs of where CPU time is being spent, you can take traces of the goroutines to understand why the system is idle when you think it shouldn't be, you can see how much memory different parts of the system are using, and so much more. It's not mentioned as prominently as I think it should be, but `go tool pprof` has this `-http=:` option that will open a web browser to let you just see everything graphically and click around, and it's an amazing experience. There were really only three things in there that Go doesn't offer: 1. Forcefully terminating processes Go doesn't allow anyone to forcefully terminate a Goroutine except the Goroutine itself. Personally, if I identified a buggy Goroutine, I would just focus on writing a patch and deploying it. Manually terminating a process is cool, but then the user types "-1" again and again, and you're just sitting there playing whack-a-mole instead of fixing the problem and deploying the fix. 2. Patching the running system without restarting it The advantages of this are difficult to enumerate. It sounds nice and clean conceptually, but I would worry about existing processes / goroutines being in unexpected states because of erroneous code that they had previously run. Having a way to gracefully shut down a system and restart it without abruptly terminating responsive client connections is much more predictable to me. 3. Seamlessly distributed execution He briefly talks about distributed Erlang towards the end of the talk. but mentions that it has serious problems and that a number of people don't recommend using it in production. Personally, even if it were nearly perfect, I think the benefits of it are limited. It's not difficult to have nodes communicate with each other using any number of other things, including proper RPC libraries all the way down to just raw TCP connections. The hard thing is service discovery, and I don't think distributed erlang meaningfully solves the problem different than other solutions. If everything is running homogeneous code, why bother your nodes with knowing about the existence of other nodes? Just use a load balancer, and then do everything internally on each node. If your systems are heterogeneous, you need a way to send the right messages to the right nodes, and that's where a named load balancer for each type of node can do just fine.
- tokenrove 6y agoI've worked a bunch in both, and Go really doesn't compare; you can't judge based on watching a talk. I find it much, much easier to write safe, robust code in Erlang, and operationally, you have so much more power to inspect the state of the BEAM. Another key BEAM thing is the process heap, which amounts to region allocation when used carefully. The reduction mechanism used for scheduling processes, though crude, is also still much lighter-weight than Go's approach. On the other hand, Erlang is a weird language and a weird environment, that takes a lot of time to really understand, so I understand why it's never going to "win", and golang tools and the runtime will continue to improve. YMMV.
- coder543 6y ago> The reduction mechanism used for scheduling processes, though crude, is also still much lighter-weight than Go's approach. I'm not sure how it could be lighter weight than what Go has implemented natively at the machine level, instead of in what amounts to a bytecode interpreter. If you have any links, I would be very interested to read more. > I've worked a bunch in both, and Go really doesn't compare I respect your experience, so it is probably a failure of imagination on my part that I simply can't imagine how the BEAM tools could be that much better. I haven't had a problem with a rogue task (or really anything else) in production with Go where I was unable to figure out what was going on extremely quickly. The tooling has been amazing for me, unlike basically every other language I've worked seriously with. The YouTube talk certainly didn't do the BEAM tools justice if they are that much better. With Go, I actually get really nice GUIs to look around the running Go process and analyze the situation, instead of just an interactive CLI session where I have to craft my own commands to find the top tasks and such. The Go pprof tools also work as an interactive shell (but for analysis, not for remote arbitrary code execution), but I would rather just have the flamegraph in front of me 99% of the time. I fully admit that I've never had a chance to use Erlang/Elixir/BEAM in any meaningful way, but I have tried to understand what they offer, and I haven't seen the compelling magic that some people talk about. Now, if someone is running a Go service without the HTTP pprof server running on some port that they can access, then yes... it wouldn't even come close to comparing to what BEAM offers when you have the option to connect to a running BEAM instance.
- juhatl 6y agoOne major thing would probably be OTP, which would be very difficult to implement as-is on top of Go. A recent comment thread [1] over at Lobste.rs explored this in more depth. Saša Jurić made an absolutely wonderful hands-on presentation [2] of what (oftentimes rather unique) value propositions Erlang/Elixir/BEAM bring to the table. It's a very tightly-packed presentation, but I strongly recommend having a look if you're curious. 1. https://lobste.rs/s/ntati1/even_go_concurrency_is_still_not_easy_with#c_jcznqs https://lobste.rs/s/ntati1/even_go_concurrency_is_still_not_... 2. https://www.youtube.com/watch?v=JvBT4XBdoUE https://www.youtube.com/watch?v=JvBT4XBdoUE
- masklinn 6y ago* Erlang builds reliability into the language and runtime through concepts of liking, supervision, … * Erlang is a much simpler language * Despite lacking a static type system, Erlang's functional bend, immutability, SSA and pattern matching makes for a rather safe language * Erlang has always been fully preempted, it didn't have to wait until 2020 for that to happen * Erlang also builds distribution in, though it's "trusted distribution" so probably of fairly limited use at large * Erlang uses shared-nothing concurrency, greatly limiting side-effects across processes, which again helps with reliability: there is no action at a distance in sequential erlang, no third-party can come in and mess with your state * when dealing with binary data, binary patterns are absolutely amazing (and rather unique)
- coder543 6y ago> * Erlang is a much simpler language Go is widely considered to be a very simple language, often too simple, so I find this claim interesting. > * Despite lacking a static type system, Erlang's functional bend, immutability, SSA and pattern matching makes for a rather safe language This is fine stuff, but I would rather have a type system, so this is just making up for a deficiency with some other stuff, so it's really just a sidegrade, not so much an upgrade or a downgrade. > * Erlang has always been fully preempted, it didn't have to wait until 2020 for that to happen With extremely rare exceptions, Go has always been fully preempted from a developer experience point of view. The fact that the underlying implementation was using function calls as yield points simply didn't matter. The fact that it is fully preempted now means it's kind of weird to still hold it against Go that they are doing the same thing as BEAM now. It is done, this is no longer a bullet point. > * Erlang also builds distribution in, though it's "trusted distribution" so probably of fairly limited use at large Go has always "built distribution in" by offering to build single static binaries. If anything, BEAM languages are harder to deploy. > * Erlang uses shared-nothing concurrency, greatly limiting side-effects across processes, which again helps with reliability: there is no action at a distance in sequential erlang, no third-party can come in and mess with your state I agree that immutability is an advantage. In general, third parties can't come in and unexpectedly mess with your state in Go either, as long as you're either maintaining your state local to a function or keeping your global variables private to each package. Keep in mind that Go's package imports must form a tree with no loops. Third party packages literally cannot see your code or any of the exported global variables, since you are importing them, and not the other way around. Go does not offer any way for packages to reflect over the whole program's state in memory, so there's no way for third party packages to go hunting around in memory and playing with your values, which would be stupid, unless they use "unsafe" to start poking at random memory addresses, and I'm certain you can do something equally dumb in Erlang with a sufficient amount of effort. It's just as crazy to think of doing something useful that way in Go as it is in Erlang. > * Erlang builds reliability into the language and runtime through concepts of liking, supervision, … This is literally the only compelling talking point I've seen for Erlang/BEAM vs Go. However, I've written large Go applications with distinct services running within the same binary, and it is possible to make extremely reliable systems. Go's context package allows you to build trees of processes that you want to be able to cancel, including cancelling specific sub-trees without affecting adjacent trees or parent trees. The single biggest footgun with building reliable systems in Go is that it prefers to crash early. So, every Goroutine that you launch, you must make sure that the first thing it does is catch any panics to avoid taking down the entire program, including unrelated Goroutines. When correctly written, a human will be immediately alerted to the bug that caused this panic (which shouldn't ever happen anyways), and the program will continue operating normally in the mean time until a human gets a chance to push out an update to fix that bug. In practice, enforcing just one rule (Goroutines must catch panics) in code reviews is not that hard, and it isn't common in my experience for most code to arbitrarily launch Goroutines -- Goroutines should be managed. In return, Go offers much better performance than BEAM, as well as most of the practical benefits of BEAM that I've seen discussed online. I think Rust is a better language than either Go or any BEAM language, but the absence of a preemptive concurrency model like Go and Erlang offer just makes it hard for me to enjoy the prospect of using Rust for general purpose network services. Once Go adds generics in the next year-ish, that should solve my biggest real annoyances with the language. I really look forward to being able to package up a number of the concurrent patterns I write into reusable packages, which will largely eliminate once and for all the need for me manually spin up a new Goroutine in the code that I'm writing and potentially forget to catch any panics.
- deleted 6y ago[deleted]
- deleted 6y ago[deleted]
- Jtsummers 6y agoErlang is a system and language for distributed (not just concurrent) programming. Go is a language for concurrent (not distributed) programming. Unless things have changed substantially since I last investigated Go, the language does not sit within a system designed for distributed computing. There are libraries you can use, but the language itself does not attempt to solve the same problems as Erlang. If you use Erlang within one node, it's roughly equivalent to Go. But Erlang is designed so that the same concurrency mechanisms you use on one node also work across a cluster of nodes. There are more differences than this, but this is probably the most critical one.
- ericlewis 6y agoSo you’re saying erlang can automatically distribute async tasks across nodes? Probably too much to comment, but how or where can I learn more about this way of thinking of it?
- Jtsummers 6y agoNot automatically, but if you connect multiple nodes into a cluster, when you spawn a process you can select which node it will be spawned on. Additionally, once the nodes and processes are running you can send messages across nodes to different processes using the same method you use for processes on a single node. [0] Shows an example of communication across nodes, as well as some preliminary material that would be helpful if you don't know Erlang. I mostly learned Erlang from Joe Armstrong's book [1], though the first edition. I'm confident the second edition is as good as the first. Learn You Some Erlang [2] is a great free (also available for purchase, but free online) book. [0] https://erlang.org/doc/getting_started/conc_prog.html https://erlang.org/doc/getting_started/conc_prog.html [1] https://pragprog.com/titles/jaerlang2/programming-erlang-2nd-edition/ https://pragprog.com/titles/jaerlang2/programming-erlang-2nd... [2] https://learnyousomeerlang.com/ https://learnyousomeerlang.com/
- tonyarkles 6y agoI’m not at home and don’t recall the library name off the top of my head (maybe libcluster?), but I recently inherited an Elixir project where the nodes were run in a k8s cluster and they automatically joined up. I was a little skeptical at first, having always manually managed that before, but... it’s buttery smooth!
- deleted 6y ago[deleted]
- deleted 6y ago[deleted]
- horlux 6y agoprocesses are lightweight and stateless