4 ms·
> The compiler accepts it just fine, though. I've never seen a concrete type in an interface before, so I decided to try it: package main type A inte
by jrockway 4y ago
> The compiler accepts it just fine, though.
I've never seen a concrete type in an interface before, so I decided to try it:
package main
type A interface {
int
M()
}
func f(x A) { // line 8
x.M()
}
It is indeed accepted if it's there by itself, but it is rejected if you try to use the interface, which is what function f does:
./main.go:8:10: interface contains type constraints
I think this ends up being a very boring reason for rejection and is somewhat irrelevant to the post that you can't actually put concrete types in interface{} definitions. It looked weird to me so I had to try it.
Since this is in the context of generics, I think the author might have been thinking about embedding types like comparable, which are interfaces (comparable is interestingly defined as `type comparable interface { comparable }`). You can, of course, put interfaces in interfaces in general (see io.ReadCloser and friends).
For the comparable case:
type A interface {
comparable
M()
}
func p(x A) {
x.M()
}
This gets its own error:
./main.go:8:10: interface is (or embeds) comparable
Very clever, because yeah, there is nothing stopping you from writing `func f(x comparable) {}`. Except this explicit check.
I don't know what the point of this comment is, since 99% of the article is not about this code block, but I guess I found it interesting.
- tapirl 4y ago> interface contains type constraints > interface is (or embeds) comparable Currently, not all interface types may be used as value types. Such types include comparable. It is very possible that all interface types could be used as value types in future Go versions, and comparable might be able to be used as value types as early as Go 1.20.
- riwsky 4y agoHuh? You can put concrete types in interface definitions as of 1.18. See the spec: https://go.dev/ref/spec#Interface_types https://go.dev/ref/spec#Interface_types
- jrockway 4y agoThe spec does say that. You can put them in the interface, but you can't use the interface. Try it: https://go.dev/play/p/9ptEd8zasML https://go.dev/play/p/9ptEd8zasML
- riwsky 4y agoYou can put them in the interface, and then you can use the interface as a type constraint for generics: https://go.dev/play/p/U25AzZndz-7 https://go.dev/play/p/U25AzZndz-7 If you wanted to argue that you can't use it everywhere you could use an interface before, that'd be all well and good—but your assertion > you can't actually put concrete types in interface{} definitions is just incorrect, in a way that lead you to misunderstand the article.
- Merovius 4y ago> It is indeed accepted if it's there by itself, but it is rejected if you try to use the interface, which is what function f does: You can't use it as a type, but you can use it as a constraint: https://go.dev/play/p/LnmudHIjAoQ https://go.dev/play/p/LnmudHIjAoQ Of course, you can then not actually instantiate that function (as the type set is empty). But using concrete types in interfaces is very possible. And it's indeed why the |-operator was introduced. It allows you to use operators: https://go.dev/play/p/I3eMDBwIcHA https://go.dev/play/p/I3eMDBwIcHA