5 ms·
The only thing golang has going for it is "goroutines". Now that all other popular languages are getting some variant of async (e.g. C#) or green thread impleme
by apta 7y ago
The only thing golang has going for it is "goroutines". Now that all other popular languages are getting some variant of async (e.g. C#) or green thread implementations (e.g. Java), it will be tough to advocate for golang for new projects given its severe shortcomings.
- Thaxll 7y agoOther language do it completely differently, there is no such thing as async in Go since the paradigm is blocking from a programmer perspective. I don't think understand how it works in Go.
- apta 7y agoI know how it works in golang. It's more or less transparent to the user, just how like it's being implemented in Java where the user doesn't designate functions as `async`, and the runtime automatically takes care of it.
- theflyinghorse 7y agoAs an aside Java's concurrency is outright confusing and just plain hard to get right. Doing concurrency in golang was like a breath of fresh air.
- apta 7y agoWhat's confusing about it? It's built on threads and mutexes, not unlike golang with its goroutines and mutexes. The main difference is that Java will be getting green threads soon, which will allow the user to spawn hundreds of thousands of them if he/she wants to.
- theflyinghorse 7y ago> What's confusing about it? Do I use Thread, Runnable, Executor, ExecutorService, or CompletableFutures? How do they interact with synchronized and Locks and which Locks do I use? Where do Semaphores fit in this picture? Sure, for someone who is in Java day in and day out and who deal with concurrent java all the time these might be very straightforward tools with clear separation of goals and intent. In my personal experience there are always easy to introduce bugs with Java's concurrency, and every time I have to do something concurrent in Java I reach for my notes first trying to refresh my memory on what's what, which I don't need to do with golang.
- apta 7y ago> Do I use Thread, Runnable, Executor, ExecutorService, or CompletableFutures It depends on what you need. Executor is an interface, so you can't use that directly, you have to use one of its implementations (like ExecutorService). CompletableFuture is what you use when you want to handle the return type of a given function or method call. I've come across so much golang code where a function that returns an error is invoked with "go foo()", and the error is ignored. The thing is, when you use golang, you have to re-write all these abstractions yourself anyway. Want to have a function execute in the background then you wait on the value? You have to pass in a channel and wait on it. What if it now returns an error? You have to pass in two channels now, or return a composite struct. In Java, you'd use a CompletableFuture and be done. Semaphores are similar to WaitGroup in golang (but with more use cases obviously). You get much more control, as well as writing code with a clear intent when you use its concurrency abstractions. In golang, you're writing much lower level code that you have to dig in to understand what's going on. Not to mention that in golang it's difficult to provide anything that comes close to what's in the java.util.concurrent package, mainly due to the lack of generics.
- jayd16 7y agoIt really not that different from C#'s async/await except go doesn't need the async markup to fix a syntax collision and every method is awaited. Java plans to implement something similar.
- crimsonalucard 7y agoWhat are you talking about? A go routine can run async to another go routine. It's async. It's just a different perspective of concurrency than node. I literally quote from go by example: https://gobyexample.com/goroutines https://gobyexample.com/goroutines "Our two function calls are running asynchronously in separate goroutines now."
- loopz 7y agoWhat they really mean by async is sync (await)! ;-) In relation to Golang: https://yizhang82.dev/go-and-async-await https://yizhang82.dev/go-and-async-await
- crimsonalucard 7y agoI'm aware of what they mean and how they are confused. You should know that the author of that article failed to mention that node is free of race conditions caused by context switching, this is a huge deal and in many cases worth the trouble of async await syntax.
- fooster 7y agoOther popular languages are not "getting" async. Asynchronous communication (just as synchronous) have been around since the dawn of computing. The choice of synchronous or asynchronous communication have their own set of tradeoffs, but in most cases the additional complexity introduced by async is IMO not really work it.
- jayd16 7y agoAsync a keyword (as in async/await although really await is the keyword) and Rust just got in November.
- theflyinghorse 7y agoGolang has simplicity going for it. It's an incredibly easy language to read and to keep in your head. Channels are nice too
- loopz 7y agoGolang is very nice and simple, yet powerful and performant in many ways by default. However, channels were way overhyped, and one really should think long and hard about wether to use them at all, ie. find specific use cases. They're based on Mutex, but slower and often end up becoming a more complex distributed pattern. Why not use channels? While sharing state/memory by communicating sounds nice, in practice you end up with coding requirements for a distributed system. Do you need one? Fine. It could even work out nicely for making a skeleton distributed monolith, before splitting into microservices. But for most common use cases, channels distribute behaviour across your system unnecessarily, and you end up needing to synchronize and clean things up between different moving parts. If you don't have clearly defined bounded contexts such a pattern can fit into, it just seems like increasing complexity for no good reason. Of course, for very straightforward implementations that you know won't grow in complexity, channels are fine, especially for simply reusing a working pattern.
- lostcolony 7y ago"Getting" and "built with" are entirely different beasts. In Java, if it gets first class green threads...does all code immediately start using those instead of an actual thread pool? Probably not; your runtime behaviors would change. Will all libraries immediately change to using them? Assuredly not, again, runtime behaviors will change, and no matter how cleanly implemented, switching and testing will take effort, for both the library maintainer and the consumer. As a consumer, then, you're left with a moving target as some of your underlying libraries make the switch, plus the related testing effort. And you also have to either make a clean switch over, or you have to mix threaded + greenthreaded libraries, which is likely non-trivial. Languages that offer a single, sufficiently powerful concurrency construct avoid that; all golang libraries support goroutines (even if they are not themselves leveraging them).
- apta 7y agoI'm not sure what you're referring to. The JVM itself will support green threads, which means that any existing blocking libraries can be called from said green threads and they will become asynchronous. The runtime will take care of multiplexing the green threads on hardware threads when an IO operation takes place for instance. It's pretty much transparent to the user.
- lostcolony 7y ago>> any existing blocking libraries can be called from said green threads and they will become asynchronous Yes, but any frameworks that currently create and manage a threadpool will not automatically be changed. As well as any libraries/frameworks that rely on async code. And any existing code you own will also not. For brand new projects, using only libraries that assumed blocking code, and had no threadpool expectations within them, sure, it's transparent. For any old projects it's not. For any libraries that were written to be async already, you don't benefit. For libraries written to manage a threadpool, you have to wait for them to be updated. And still, as now, God help you if you want to mix and match, to use a library written to be async, and a library written to use a threadpool...but of course, now compounded because you want to write sane, performant, readable blocking code using green threads. You have to deal with all those incongruities and make them all work together. Languages that have an M:N threading mechanism from the get go (hah!) get the benefit of everything building atop that from the beginning.