> [For golang] One could say that this is only because there is an
> implied dynamic_cast (but with worse performance, since it requires a
> runtime lookup) at every location where an object is used.
You are confused. Go has static typing. As in, checked at compile-time. Code that misuses types will not compile.
Think of it this way: if you refer to a type T in a C++ template, and then use T::foo, you're not doing a dynamic_cast. You're just using the normal type system. If T does not have a foo method, the code will not compile. Similarly, in Go, you will get a compile-time, not runtime, error, if you try to use methods on an object that don't exist.
Also, you seem to be confused about C++ as well. dynamic_cast *always* "requires a runtime lookup" on the RTTI (runtime type information) in C++. If you do not compile with support for RTTI, you cannot use dynamic_cast. C++ templates, on the other hand, are a completely compile-time mechanism. I don't know why you would say that templated code is not as "strongly-typed" as other C++ code.
> While I fail to see any reason to prefer extraneous syntax over a library,
> there is in fact some syntax in D intended to support multithreaded
> programming: the 'immutable' and 'sharable' type keywords, for example,
> plus the fact that global variables occupy thread-local storage by
> default. Assurance that shared state cannot be mutated behind the scenes
> (not just through a given reference, like 'const', but *anywhere* in the
> process) allows large messages to be passed efficiently and safely.
There's a lot of syntax in D, but is it the right syntax? I think we are going to have to agree to disagree.
I also would like to note in passing that C/C++ have the const, restrict and __thread keywords, which could be used to provide exactly the same message-passing interface you describe in D. In fact, there have been a lot of them created over the years.