TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Notes on structured concurrency, or: Go statement considered harmful

301 点作者 m0meni大约 7 年前

43 条评论

arghwhat大约 7 年前
What.<p>This article proposes a &quot;nursery&quot;, which is just a wrapped sync.WaitGroup&#x2F;pthread_join&#x2F;futures::future::join_all&#x2F;a reactor that waits for all tasks to terminate&#x2F;etc.<p>It then uses an exception-like model for error propagation to &quot;solve&quot; error handling (which is fairly easy to handle with a channel).<p>The construct is a decently usable, already applied tool to handle a set of problems, but the article takes the issue way out of proportions and overhypes the proprosed solution. The &quot;with&quot; example for benefits to not having a &quot;go&quot; statement seem rather bogus, especially seeing that such RAII constructs do not exist in Go (no destructors, remember?).<p>Trying to claim that &quot;go&quot; is as terrible as the original &quot;goto&quot; is ignorance of the original problems. Bad use of goto can be a nightmare to track (as the author tried to illustrate), but goroutines do not jump around, they <i>branch</i> from the main goroutine, following normal control flow from there. They are easy to follow, and the language is designed so that you can throw around with them and forget them without them causing you problems.<p>Also, this article is comparing a list of concurrency constructs and one parallism construct (pthread_create—threading.Thread doesn&#x27;t count as parallism due to GIL) to <i>callbacks</i>, something which have nothing to do with concurrency <i>at all</i>. Very odd.
评论 #16922455 未加载
评论 #16924391 未加载
评论 #16925491 未加载
评论 #16924690 未加载
评论 #16928444 未加载
评论 #16926718 未加载
评论 #16927433 未加载
评论 #16925022 未加载
评论 #16925350 未加载
erpellan大约 7 年前
The author appears to have reinvented Communicating Sequential Processes (CSP).<p><a href="http:&#x2F;&#x2F;www.usingcsp.com&#x2F;cspbook.pdf" rel="nofollow">http:&#x2F;&#x2F;www.usingcsp.com&#x2F;cspbook.pdf</a><p>The (simplified, and as I understand it) gist of concurrency in CSP is that the program is expressed as a series of parallel (PAR) and sequential (SEQ) operations.<p>Everything in a PAR block will run in parallel and all their outputs will be collected and fed as the input to the next SEQ. Everything in a SEQ will run sequentially as a pipeline until the next PAR. Every PAR must follow a SEQ and vice versa, as two PARS or SEQS next to each other will simply coalesce.<p>eg.<p><pre><code> PAR longCall1 longCall2 longCall3 SEQ reduceAllThreeResults doSomethingWithTheReducedResult PAR nextParallelOp1 nextParallelOp2 </code></pre> etc.
评论 #16923837 未加载
评论 #16923542 未加载
评论 #16923619 未加载
评论 #16924212 未加载
评论 #16924379 未加载
评论 #16924197 未加载
coldtea大约 7 年前
It&#x27;s amazing how many people managed to skim through the post, and hammer on their own preconceptions and facile counter-arguments, for things that are all addressed in the argument.<p>And that&#x27;s for a very well written post, that tries to address all common issues.<p>And yet, people manage to get it wrong, or write facile responses like &quot;re-implementing the fork&#x2F;join&quot;.<p>Not to mention missing the whole nuance of what the author is talking about, which is not about novelty of a feature, but about what it allows us (and even more so, what it constraints us).<p>It&#x27;s like as if people being shown for loops and structured programming in the 60s responded with &quot;this proposal just reinvents gotos&quot;. Or worse, that &quot;this is more restrictive that gotos&quot;.<p>Yes, the author knows about the Erlang&#x27;s model. He writes about it in the post, and about how you can use his proposal to do something similar.<p>Yes, the author knows about Rust&#x27;s model. In fact Graydon Hoare, the creator of Rust (now working at Apple on Swift), has read the post&#x27;s initial draft and gave his comments to the author.
评论 #16931332 未加载
Animats大约 7 年前
This addresses the wrong problem. The real issue is control over data shared between threads, not control flow.<p>C&#x2F;POSIX type threads have no language support for indicating what data is shared and which locks protect which data. That&#x27;s a common cause of trouble. The big question in shared memory concurrency is &quot;who locks what&quot;. Most of the bugs in concurrent programs come from ambiguities over that question.<p>Early attempts to deal with this at the language level included Modula&#x27;s &quot;monitors&quot;, the &quot;rendezvous&quot; in Ada, and Java &quot;synchronized&quot; classes. These all bound the data and its lock together. Rust&#x27;s locking system does this, and is probably the most successful one so far. (Yes, the functional crowd has their own approaches.)<p>Go talked a lot about controlling shared memory use. The trouble with goroutines, as Go programmers found out the hard way, was that the &quot;share by communicating, not by sharing&quot; line was bogus. Even the original examples had shared data. But the language didn&#x27;t provide much support for controlling that sharing.<p>Python is basically at the C level of sharing control over data, except that the Global Interpreter Lock keeps the low-level data structures from breaking. This prevents Python programs from doing much with multi-core CPUs. Since this is just another thread library for Python, it has the same limitations.<p>Real concurrency in Python with disjoint data, and without launching a heavy-weight subprocess, would be a big win. But this isn&#x27;t it.
评论 #16925282 未加载
评论 #16930944 未加载
评论 #16925089 未加载
lclarkmichalek大约 7 年前
This is usually why I end up using <a href="https:&#x2F;&#x2F;godoc.org&#x2F;golang.org&#x2F;x&#x2F;sync&#x2F;errgroup" rel="nofollow">https:&#x2F;&#x2F;godoc.org&#x2F;golang.org&#x2F;x&#x2F;sync&#x2F;errgroup</a> instead of straight go statements, as it addresses some of the cancellation and error propogation issues. When I think of my use of naked go statements, it&#x27;s usually for periodic tasks; having something similarly structured for them would be a clear win to me (though potentially the impact is less significant, as it&#x27;s less painful to write a well formed periodic task using the go statement and context).
评论 #16922873 未加载
评论 #16922458 未加载
评论 #16928574 未加载
评论 #16922180 未加载
评论 #16923329 未加载
m0meni大约 7 年前
I thought the title was kinda clickbaity, but it turned out to be a great article. Also the comparison to goto really effectively conveyed the point he was trying to make. I have two questions though:<p>* Does anything else like this currently exist (other than the Trio library he mentions), which shows that it&#x27;s a superior paradigm in practice?<p>* What are the cons to this approach? Why not do it?
评论 #16922062 未加载
评论 #16922158 未加载
评论 #16924803 未加载
评论 #16923773 未加载
评论 #16922803 未加载
leshow大约 7 年前
&gt; As a result, every mainstream concurrency framework I know of simply gives up. If an error occurs in a background task, and you don&#x27;t handle it manually, then the runtime just... drops it on the floor and crosses its fingers that it wasn&#x27;t too important.<p>You ought to look into Erlang and Elixir on the BEAM vm&#x2F;runtime. It&#x27;s arguably the best example of this kind of concurrency (greenthreading, async) done properly with regards to error handling.<p>I don&#x27;t write Elixir or Erlang, but I believe this process is managed by the supervisor. You can select various behaviours for when a process crashes or errors out[1]. For instance, you can have a process simply restart after it crashes. Combined with a fail-fast mentality, this produces remarkably fault tolerant and long lived applications.<p>[1]: <a href="http:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;design_principles&#x2F;sup_princ.html" rel="nofollow">http:&#x2F;&#x2F;erlang.org&#x2F;doc&#x2F;design_principles&#x2F;sup_princ.html</a>
评论 #16924988 未加载
shadowmint大约 7 年前
This is very very long to explain a very simple pair of ideas:<p>1) You should be able to declare scoped blocks that mandate execution of all tasks started in that block ends when the scope ends.<p>2) This is fundamentally superior to all other forms of concurrency.<p>I get it; this is basically what async&#x2F;await gets you, but conceptually you can spawn parallel tasks inside an awaited block, and know, absolutely that all of those tasks are resolved when the await resolves.<p>(this is distinct from a normal awaited block which will execute tasks inside it sequentially, awaiting each one in turn).<p>...seems like an interesting (and novel) idea to me, but I flat our reject (2) as ridiculous.<p>Parallel programming <i>is hard</i>, but the approach from rust, to give you formal verification, instead of arbitrarily throwing away useful tools seems much more realistic to me.
评论 #16922979 未加载
评论 #16923263 未加载
评论 #16922439 未加载
评论 #16922591 未加载
评论 #16922302 未加载
评论 #16922776 未加载
jaffee大约 7 年前
I LOVE Go&#x27;s concurrency model, but this article has won me over (pending some experimentation anyway).<p>If you just skimmed, this is actually worth a careful read. The parallels between &quot;go&quot; and &quot;goto&quot; are explained very clearly, and you get some awesome Dijkstra quotes to boot!
评论 #16924505 未加载
评论 #16922846 未加载
pnathan大约 7 年前
Article persuasive <i>prima facie</i> and arguments plausible. I&#x27;ve had to reinvent a structured method of managing threads a number of times, unfortunately.<p>Author is a PhD student, which bodes well for not reinventing wheels dumbly. Therefore, I look forward to the lit review of other concurrency &amp; parallelism work through the last 40 years, which this writeup notably lacks (author mentions his stack of papers to review).<p><i>Your ideas are intriguing to me and I wish to subscribe to your newsletter.</i><p>ed: author has phd, not is a student.
评论 #16924313 未加载
jnwatson大约 7 年前
What timing!<p>My project is currently struggling with how to migrate to Python async. The biggest challenge is the place where async and sync interface.<p>Just the other day, my colleague was wondering out loud about the possibility of using a context manager to constrain the scope of async. This is it. This is exactly what we were looking for.
shalabhc大约 7 年前
&quot;our call stack has become a tree&quot;<p>This is a really useful property to have and reason about.<p>Instead of several independent coroutines with arbitrarily overlapping lifetimes, we can now think of all coroutines as organized in a <i>single hierarchy</i> with properly nested lifetimes.<p>The function call stack becomes a call tree - each branch is a concurrent execution.
bgorman大约 7 年前
I have yet to see any of these problems in core.async (Clojure&#x27;s version of goroutines). core.async has enabled fantastic programming abstractions like async pipelines using transducers and &quot;socket select&quot; type programming. Perhaps functional programming is the solution to solve concurrency issues.
评论 #16923025 未加载
acjohnson55大约 7 年前
So, my initial thought when reading was &quot;yeah, it&#x27;s async&#x2F;await&quot;. But it&#x27;s subtly different than that though.<p>You&#x27;re free to spawn parallel tasks in async&#x2F;await -- you just use Promise.all or Future.sequence, or whatever your language provides to compose them into a larger awaitable.<p>Nurseries seem to go a step beyond this by reifying the scheduling scope as the eponymous nursery object. This means that you have a new choice when the continuation of your async task happens: a nursery pass in from some ancestor of the call tree. My gut says that this offers similar power as problematic fire-and-forget async tasks, but takes away the ability to truly forget about them.<p>My guess is that, in practice, you end up with some root level nursery in your call stack to account for this. But account for it you must! And while the overwhelming sentiment in these comments is pretty dismissive, I&#x27;d caution against downplaying the significance of this. It&#x27;s basically like checked exceptions or monadic error handling.<p>I also think about how this maps to task or IO monad models of concurrency. It seems like there&#x27;s an inversion of control. Rather than returning the reification of a task to be scheduled later, the task takes the reification of a runtime, upon which to schedule itself. I&#x27;m not sure what the ramifications of this are. Maybe it would help with the virality of async return values [1], but at the cost of the virality of nursery arguments.<p>Lastly, one thing this article nails is the power of being able to reason about continuation of control flow. Whether or not nurseries have merit as a novel construct, this article still has a lot of educational use by making this argument very clearly. Even if the author is wrong about nurseries being &quot;the best&quot;, it sets a compelling standard that all control mechanisms--async or not--should have to explain themselves against.<p>I do have a couple questions:<p>- In the real world, would library APIs begin to get clogged with the need for a nursery on which to run an async task? Think async logging or analytics libraries.<p>- Would usages similar to long-running tasks that receive async messages be compatible? I&#x27;m thinking of usages of the actor model or channel model that implement dynamic work queues.<p>- Does this increase the hazard presented by non-halting async tasks?<p>[1] <a href="http:&#x2F;&#x2F;journal.stuffwithstuff.com&#x2F;2015&#x2F;02&#x2F;01&#x2F;what-color-is-your-function&#x2F;" rel="nofollow">http:&#x2F;&#x2F;journal.stuffwithstuff.com&#x2F;2015&#x2F;02&#x2F;01&#x2F;what-color-is-y...</a>
panic大约 7 年前
This other post from the same blog gives some more concrete background on why this sort of structured concurrency is a good idea: <a href="https:&#x2F;&#x2F;vorpus.org&#x2F;blog&#x2F;some-thoughts-on-asynchronous-api-design-in-a-post-asyncawait-world&#x2F;" rel="nofollow">https:&#x2F;&#x2F;vorpus.org&#x2F;blog&#x2F;some-thoughts-on-asynchronous-api-de...</a>
cousin_it大约 7 年前
Didn&#x27;t expect to say this, but the article is completely right! This is obviously the right way to write concurrent programs. Kudos for writing this.<p>One question though. The first part of the article says that &quot;onclick&quot; handlers should be replaced with nurseries as well. But I don&#x27;t see how. Can someone explain?
评论 #16925346 未加载
评论 #16922380 未加载
评论 #16925384 未加载
catnaroek大约 7 年前
Lately, I am of the idea that the real problem with how we do concurrency is that we have yet to figure out a way to do it without first-class procedures. When we spawn a thread, even in a low language such as C, we use something to the effect of:<p><pre><code> launch_thread(function, perhaps, some, initial, data); </code></pre> The trouble with this approach to concurrency is twofold:<p>(0) It forces a hierarchical structure where one continuation of the branching point is deemed the “parent” and the others are deemed the “children”. In particular, if the forking procedure was called by another, only the “parent” continuation may return to the caller. This is unnatural and unnecessarily limiting. Even if you have valid reasons to guarantee that only one continuation will yield control back to the caller (e.g., to enforce linear usage of the caller&#x27;s resources), the responsibility to yield back to the caller is in itself as a resource like any other, whose usage can be “negotiated” between the continuations.<p>(1) It brings the complication of first-class procedures when it is often not needed. From a low-level, operational point of view, all you need is the ability to jump to two (or more) places at once, i.e., a multigoto. There is no reason to require each continuation to have a separate lexical scope, which, in my example above, one has to work around by passing “perhaps some local data” to `launch_Thread`. There is also no reason to make “children” continuations first-class objects. If you need to pass around the procedure used to launch a thread between very remote parts of your program, chances are your program&#x27;s design is completely broken anyway. These things distract the programmer from the central problem in concurrent programming, namely, how to coordinate resource usage by continuations.
_Codemonkeyism大约 7 年前
The main culprit to me in Golang seems to be channels, not goroutines. If your workflow essentially is defined by a mesh of channels and goroutines, it&#x27;s hard to reason or understand.<p>I have no direct practical knowledge of Golang, but working on a large application that used BlockingQueue for concurrent communication and one which extensively used services buses for communication - both were hard to understand and reason about flow.<p>After some years with Scala Futures I&#x27;d say they work well and reason well. They can be seen as normal function calls returning Future instead of another &#x27;container&#x27;.<p>They reflect the black box mentioned in the article, with one way in and one way out (e.g. when a method returns Future[_]).<p>The point about error handling: We use Option,Seq.empty on read error handling, Validation on create&#x2F;write and Either on side effects (like sending mail).<p>(yes, they are still leaky abstractions e.g. when debugging, but work fine most of the time)
评论 #16924494 未加载
_bxg1大约 7 年前
Interesting ideas, and well-worded.<p>You could achieve something similar in JavaScript with Promise.all() and await:<p><pre><code> await Promise.all([ asyncFunc1(), asyncFunc2(), asyncFunc3() ]) </code></pre> Of course, that&#x27;s not language-level and the point seemed to focus more on eliminating traditional branching than just adding another way to do it.
评论 #16925820 未加载
评论 #16925727 未加载
woah大约 7 年前
Worst title ever. I never complain about this stuff, but can someone please change it? You think it’s going to be some analysis about Go, but instead it’s someone pushing their library.
评论 #16923013 未加载
ptero大约 7 年前
I was underwhelmed by reading this (maybe due to a clickbaity title and IMO sketchy extension of badness from goto to the go statement).<p>That said, the article has good technical content. It proposed a new concurrency library with interesting properties. Concurrency comes with additional cost. The library proposes a paradigm to minimize certain costs and should provide punchy examples of how things can be done simply and efficiently with it.<p>But instead it is picking shallow fights with the go statement (does the author know about the &quot;sync&quot; package and WaitGroup)? Overall I found the advocacy section <i>WAY</i> too long. Use most of that real estate to show goodness of your library, not on trying to punch holes in the competitors. My 2c.
liveoneggs大约 7 年前
<a href="http:&#x2F;&#x2F;rvirding.blogspot.com&#x2F;2008&#x2F;01&#x2F;virdings-first-rule-of-programming.html" rel="nofollow">http:&#x2F;&#x2F;rvirding.blogspot.com&#x2F;2008&#x2F;01&#x2F;virdings-first-rule-of-...</a>
amluto大约 7 年前
I’m wondering if some promise&#x2F;future systems already provide a similar guarantee. The main useful property of the nursery system is that a function’s signature indicates whether that function leaves a background task running. If you can guarantee that promises&#x2F;futures are dropped if they go out of scope, then you get a similar guarantee. Similarly, if you have a system where promises don’t actual run their background parts unless someone is waiting for them, then there are no leaky background tasks.
jey大约 7 年前
I&#x27;m really growing fond of the async&#x2F;await abstraction. How do I get this in more C-like languages like Go, Rust, or C++? (I have a bunch of C++ code that I want to call via C ABIs.)<p>I&#x27;m intrigued by libdill but it&#x27;s mysterious enough that I&#x27;m scared to include it in my project -- I don&#x27;t want to risk getting sidetracked by having to debug my concurrency primitives.
评论 #16922836 未加载
评论 #16922765 未加载
benjohnbarnes大约 7 年前
I found this pretty fascinating and I&#x27;m looking forward to hearing the theoreticians chew it over.<p>A question I had was with the API that&#x27;s been chosen. The `nursery` is chosen as the reified object, and a function `start_soon` is exposed on it. Perhaps in other parts of the library there are other methods exposed on `nursery`? If not, in some languages it seems like the `start_soon` method itself would make more sense as the thing to expose. In use, it might do like this:<p><pre><code> ... nusery { (go) in go { this_runs_concurrently_in_the_nursery } go { this_also_runs_concurrently_in_nursery } &#x2F;&#x2F; make a regular function call passing it the nursery&#x27;s `go` some_func(go) } ... </code></pre> And elsewhere:<p><pre><code> ... func some_func(go) { do_something() go { nursery { &#x2F;&#x2F; This nursery is within the outer one. (go2) in go2 { do_stuff } go2 { do_more_stuff } } } } ...</code></pre>
Osiris大约 7 年前
&gt; whenever you call a function, it might or might not spawn some background task. The function seemed to return, but is it still running in the background? There&#x27;s no way to know without reading all its source code, transitively. When will it finish? Hard to say.<p>This reminds of me &quot;colored functions&quot; (red vs blue) where it becomes imperative to know if a function you are calling returns a value or a Future&#x2F;Promise.<p>Some languages allow annotating a function to indicate as such so the IDE can help. His particular solution he presents actually doesn&#x27;t address this question: Is your function sync or async? You still have to know when calling a function if it&#x27;s async and needs to be in a nursery or not.<p>Should a programming language abstract away whether a function is async or not? async&#x2F;await is a step forward (C#&#x2F;JS) but it still requires knowing if the child function is async or not.
评论 #16926959 未加载
ufmace大约 7 年前
I found it an interesting idea and writeup. It&#x27;d be good to see what could be done in a language that implemented this - concurrency only allowed in the context of nurseries. On the downside, though, I think there&#x27;s a lot of concurrency patterns that could only be implemented by creating a nursery near the top level of the application and passing it around all over the place, thus getting you pretty much right back where you started.<p>Want a web app that sets up some long-running thing to run in the background while the request returns quickly? Well then you&#x27;re going to need a nursery above the level of the request which is still available to every request. I don&#x27;t see what that gives you above conventional threading. Oh, and you&#x27;d also need to implement your own runner in a thread to have a task failure not bring down the whole application.
评论 #16932221 未加载
mamcx大约 7 年前
Is incredible how easy is to miss the point of this.<p>Let me try with something else.<p>Imagine you have try&#x2F;catch&#x2F;finally BUT NOT AS CONTROL FLOW CONSTRUCS but &quot;just api calls&quot;.<p>So, you language need to be used like:<p><pre><code> foo() exceptions.try{ bar() this.catch{ } } </code></pre> It means, you need to remember to ALWAYS REMEBER to &quot;close&quot; the start of the call.<p>Imagine how bad this could be. If only &quot;try&#x2F;catch&quot; was as with &quot;IF&#x2F;ELSE&#x2F;ENDIF&quot; so you not do something stupid like:<p><pre><code> foo() exceptions.catch{ what?() } bar()</code></pre>
pmarreck大约 7 年前
I don&#x27;t like the term &quot;nursery&quot; (maybe &quot;highway&quot; or &quot;complex&quot; or... something else) but this seems to be a good design change, unless I&#x27;m missing something
评论 #16925879 未加载
评论 #16928841 未加载
评论 #16927989 未加载
earenndil大约 7 年前
His note on resource cleanup doesn&#x27;t really make sense -- or, rather, it only makes sense if you&#x27;re using python&#x27;s solutions for it. What about something like, say, c++ where you have a smart pointer that keeps track of the number of references to it, to store your file pointer? Then when you pass that to your concurrent function, it won&#x27;t get cleaned up, until that other thread finishes, then that reference to it will be lost and it&#x27;ll clean itself up.
atrn大约 7 年前
Coming from an occam&#x2F;transputer background (in the 1980s) I felt goroutines were too low level. Luckily its trivial to add a PAR-like construct via sync.WaitGroup (e.g. github.com&#x2F;atrn&#x2F;par). That said Go&#x27;s channels are far easier to work with - buffering and multi-producer&#x2F;-consumers being very common needs which, in occam, you implement yourself. The lack of guards in Go&#x27;s ALT (select) is a shame and the nil channel hack is just that, a hack.
egnehots大约 7 年前
There are other approaches. State machines, reactors are often used in low level layers and the Actor model for some high level design.
评论 #16922337 未加载
titzer大约 7 年前
The author might want to take a look at Habanero Java, which has all of this and more.<p><a href="https:&#x2F;&#x2F;wiki.rice.edu&#x2F;confluence&#x2F;display&#x2F;HABANERO&#x2F;Habanero-Java" rel="nofollow">https:&#x2F;&#x2F;wiki.rice.edu&#x2F;confluence&#x2F;display&#x2F;HABANERO&#x2F;Habanero-J...</a>
glorioustao大约 7 年前
go statement is just another form of explicit process creation, fork&#x2F;join pattern. What the author suggested is just similar to cobegin&#x2F;coend -- implicit process creation.<p>cobegin&#x2F;coend are limited to properly nested graphs, however fork&#x2F;join can express arbitrary functional parallelism (any process flow graph) [1]<p>Yes, for graceful error handling it needs to form some sort of process tree or ATC(Asynchronous transfer of control), which is implemented in Erlang&#x2F;OTP and ada programming.<p>[1] <a href="http:&#x2F;&#x2F;www.ics.uci.edu&#x2F;~dillenco&#x2F;compsci143a&#x2F;notes&#x2F;ch02.pdf" rel="nofollow">http:&#x2F;&#x2F;www.ics.uci.edu&#x2F;~dillenco&#x2F;compsci143a&#x2F;notes&#x2F;ch02.pdf</a>
xfer大约 7 年前
How is this different than calling join(), after spawn()?
评论 #16922275 未加载
themihai大约 7 年前
Well they lost me at the callbacks... if go statements are harmful and callbacks are not then I rather prefer the harmful way.
评论 #16924021 未加载
imauld大约 7 年前
How did someone manage to write a post that long discussing Go and it&#x27;s concurrency model and not once mention channels?
bitL大约 7 年前
That&#x27;s pretty cool! Thanks for enriching my day and good luck with your framework!
Fellshard大约 7 年前
A point I believe the author has missed: Goroutines aren&#x27;t simply forked functions, but are abstracted as independent, autonomous processes. Now, that doesn&#x27;t mean &#x27;go&#x27; is a sufficient tool to reason about goroutines, but this may also not be as useful a solution as he touts it to be.
评论 #16924852 未加载
ychen306大约 7 年前
Hmm.. Looks like the author is reinventing fork-join style parallelism...
评论 #16925767 未加载
gafferongames大约 7 年前
This is absurd. The only thing &quot;go&quot; has in common with &quot;goto&quot; is the first two letters.
dingo_bat大约 7 年前
I think this has a lot of merit. And the analogy to goto is very apt and deep. I suspect that 20 years later all our concurrency interfaces may well look like this.<p>However, the momentum of today&#x27;s programming community may be too great to surmount. When goto was criticized, there were fewer people to convince to give up on it. Now, there are orders of magnitude more devs. And all of them are comfortable in the current way of doing things.
zzzcpan大约 7 年前
I know people already said it, but causality, resource cleanup and error handling are all solved with Actor model in a more general, more flexible and more reliable way than nurseries.<p>If you think reasoning about concurrency is hard, try testing and modelling it, especially for something distributed. This is where naive ideas about concurrency should start to fail and a need in solid foundation arise.