The specific case I ran into was using a database library. The function that would compose a database query with custom parameters took interface{} as the parameter type instead of sql.Valuer. I thought this was a mistake, but when I asked the library's author, they said they had to make it take interface{} because primitive types cannot implement sql.Valuer.
Nothing in your comment indicates this is not still the case. You can't implement methods on primitive types, can you? That's a shame.
That's correct, and part of the larger notion that you cannot add methods to types from another module. (Primitive types come from the same pseudo-module that declares append, len, etc.)
Think about it. How would you cleanly implement this? If you allow e.g.
Then what does the compiler do when two modules declare that method? You could forbid it, but this will lead to situations where existing application code breaks because a library is updated and the new library version includes a method that was already implemented (possibly differently) by the application.
The other option is to allow implicit casts such as
func foo(s Stringer) { fmt.Println(s.String()) }
foo(1) # implicitly casts to ValueMeters to satisfy Stringer interface
But then you run into the same problem. How would you select (forward-compatibly!) the right interface implementation to cast to?
EDIT: The only solution that I can see is to allow function overloads:
Without having thought it through very far, I think that this can be done consistently (precisely because all types are final in Go once the module is cmplete), but it would probably still lead to some surprising behavior.
Actually, I just now see a problem with this:
func foo(x int) { ... }
func foo(x uint) { ... }
foo(0) # which one to use?
Literals don't have a type in Go until they're used in a place that requires a specific type. To make this example even more interesting, consider this:
func foo(x int) uint { ... }
func foo(x uint) int { ... }
fmt.Printf("%t", foo(0)) # prints "uint" or "int", but which?
Nothing in your comment indicates this is not still the case. You can't implement methods on primitive types, can you? That's a shame.