Futures, maybe (though without generics you'll be either very dynamic or write a new future for each struct, of course).
But async/await is a syntactic feature and can't be implemented in a language without macros and/or continuations. Basically `await` is a keyword which returns a future that will execute the rest of the function as written. Something like this is relatively easy to implement:
async Task<int> Foo() {
int i := await Bar();
return i + 1;
}
You could re-write it to something like this in Go: func Foo() func()(int){
var reply chan int
go func() {
reply <- Bar()
}
return func()(int) {
i := <- reply
return i
}
}
Or something similar. Maybe you could even reduce the boilerplate, though it's already much worse than the C# verison. But this is much more difficult to re-write in Go: async Task<int> Foo() {
auto sum = 0;
foreach (auto x in someEnumerable) {
switch(x) {
case 1:
sum += await Bar(x);
goto case 2;
case 2:
sum /= await Bar(x);
break;
}
}
return sum;
}
Assuming you want to keep the asynchronicity, this gets much uglier to implement in terms of channels (not that this is very common code).