I like Rust and Go both, but I think that Go was intended not to be "exciting", but to provide a fairly narrow set of benefits and to be production ready quickly (I'm not really sure if the long term roadmap is for Go to stay there, or use production experience to grow into something with broader advantages, just carefully selected based on needs revealed through production use.)
I was really a little bit disappointed to learn that go (touted for it's goroutines) doesn't have actors, i would love to have the erlang style, network aware actor model in a language i belief i could learn easily ;)
Without that, i don't see so much noveltly :(
All in all i don't see how goroutines can compare to the Erlang model at all (
I am no fan of Scheme either, but at least I admit it had one big contribution: the idea that a language ought not to be measured by the number of its features, but by the number of things its features can express when combined.
The situation with Go is completely different. Go is just... meh. Its concurrency model is worse than Erlang's, which predates it. Its type system is worse than Standard ML's, which predates it. Its runtime efficiency is noticeably worse than C++'s, especially so when using customized allocators and avoiding exceptions and RTTI. In short, Go is mediocre.
You haven't mentioned defer/panic/recover, which seems like the strangest aspect of the language to me. It's similar to exceptions, but the mechanism of action is much more complicated semantically.
As I understand it (and I'm not a Go expert), but panic/recover is not idiomatic Go, and they much prefer the style of using a second return parameter for errors. defer is just a useful syntactic construct that becomes complicated when you add in exceptions (but no more so than calling the destructors in C++ stack unwinding).
> defer is just a useful syntactic construct that becomes complicated when you add in exceptions (but no more so than calling the destructors in C++ stack unwinding).
defer is quite a bit more complex than C++ stack unwinding, because it's dependent on implicit mutation of per-function state and can't really be implemented any other way in the general case. This shows up when you call defer repeatedly in a loop, for example.
Rust is a longer-term, more ambitious effort.