> You are confused. Go has static typing. As in, checked at compile-time. Code that misuses types will not compile.... I don't know why you would say that templated code is not as "strongly-typed" as other C++ code.
Perhaps I am confused after all. I fail to see how Go can be statically typed, with, in particular, specific types for each function parameter, as well as "duck typed", where any type which provides certain methods will be accepted. If types must be known at compile-time then what would be the point of "duck typing"?
Note, too, that it is entirely possible to misuse types in a "duck typed" language, even with compile-time checking. Since there is no information regarding the connections between types (namely inheritance), any type which provides the right method signatures will be accepted, whether or not they were intended to be used in that fashion. This is where explicit interfaces and inheritance can prove very useful as a way of preventing semantic errors.
Go code and C++/D templates are not as strongly-typed for the reasons I stated above: namely, any type with a matching signature will be accepted, even if that use of the type's members is incorrect or even undefined. Classes with inheritance are more strongly typed because they explicitly state that they implement the expected interface--the semantics, not just the type signatures.
> 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++.
RTTI is only required to test that the object you are casting is derived from the class you are casting to. As such, it is a very simple test. In Go the compiler must either generate separate code for each type (like C++/D template functions) or else look up the member offset or function pointer by name for each object at runtime, which seems to me quite likely to be far more expensive.
> 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.
The 'const' and 'restrict' keywords in C++ are not equivalent to 'immutable' in D. Immutable data is guaranteed to never change, and this is enforced by the compiler. You can't pass mutable data to a function expecting immutable, for example. (You *can* pass mutable data to a function which accepts 'const' data, in addition to immutable data.) The 'restrict' keyword is just a declaration of intent. If you declare a pointer 'const' and 'restrict' then the compiler will optimize the code on the assumption that the data cannot be altered via another pointer, but it is up to the programmer to ensure that this is actually the case. I do not think it insignificant, either, that in D you have to specifically declare data as shareable between threads (again enforced by the compiler, unlike in C/C++), whereas in C/C++ all global data is shared by default and you must use __thread to make it private. In D thread-safety is the default; in C/C++ it is a rarely-used compiler-specific extension. (C++0x will supposedly add TLS as a standard storage class.)