5 ms·
I think this proposal looks pretty good, but it does expose something odd about the core language. Given this example from the article: func Max(type T ord
by EdSchouten 8y ago
I think this proposal looks pretty good, but it does expose something odd about the core language. Given this example from the article:
func Max(type T ordered) (a, b T) T {
if a < b {
return b
}
return a
}
It would make me assume that if I were to write a function that looks like this, it would at least accept the same type of arguments:
func AnotherFunction(a, b ordered) {
...
}
As in, substituting 'T' with 'ordered'. Unfortunately, it would not. In this case, the arguments are interface objects, which are pointers under the hood. Calls to the function have to be adjusted to pass in pointers. I think Go would have been more consistent if instances of interface objects always had to be prefixed by * . Concretely, this would throw a compiler error:
func ReadStuff(r io.Reader) {
...
}
Instead, it should be written as follows:
func ReadStuff(r *io.Reader) {
...
}
As in, r is a pointer to an object that implements the io.Reader interface.
- roganartu 8y agoThis is complicated by the fact that a struct method can have a pointer or a non-pointer receiver. They can't be mixed, but consider the following: type Foo struct {} type Bar interface { Baz() } You could implement the interface either with a pointer receiver: func (f *Foo) Baz() {...} Or with a non-pointer receiver: func (f Foo) Baz() {...} Pointer receivers are more common for various reasons, but non-pointer receivers are still perfectly valid. If you force interface arguments to be prefixed with a * then you end up with confusing usage depending on how you initialize the variable being passed and whether the interface was implemented using pointer receivers or not. eg, for your ReadStuff example above, there are the following possibilities: reader := SomeReader{} pointerReader := &SomeReader{} // SomeReader implements io.Reader with a pointer receiver ReadStuff(&(&reader)) // This isn't actually valid, compiler will throw "cannot take the address of &reader" ReadStuff(pointerReader) // SomeReader implements io.Reader with a non-pointer receiver ReadStuff(&reader) ReadStuff(*pointerReader)
- majewsky 8y ago> It would make me assume that if I were to write a function that looks like this, it would at least accept the same type of arguments: func AnotherFunction(a, b ordered) { ... } Not really. If we consider `ordered` an interface, then `func(a, b ordered)` does not enforce typeof(a) == typeof(b), only that both types implement `ordered`.
- EdSchouten 8y agoExactly, which is why I said: "it would at least accept"