go-internals
go-internals copied to clipboard
chapter2: Interface conversions. Type assertions where the destination type is itself an interface.
It's quite possible this is covered in Chapter 2 or elsewhere, and I missed it, because I am lazy. If so, apologies!
Based on my C++ background, I believe I completely understand how Go handles your type-assertion example here. It can just, as you say, compare Eface._type with type.uint32.
But I cannot fathom how the following code works!
type Craft interface { Float() }
type Car struct {}
type Boat struct {}
func (c Boat) Drive() {}
func (c Boat) Float() {}
func (c Car) Drive() {}
var vface interface { Drive() }
var cface interface { Float() }
func main() {
b := Boat{}
vface = b
cface = vface.(Craft)
}
On the line cface = vface.(Craft), all the compiler knows about vface is that it is some kind of Vehicle. (Incidentally, its _type compares equal to type.Boat; but nobody said anything about Boat on this line, so that can't be relevant to anything.) So how does the runtime know how to convert an arbitrary Vehicle into a Craft?
If you initialize b := Car{} instead, then you get panic: interface conversion: main.Car is not main.Craft: missing method Float at runtime — which is exactly what I would expect — but, I don't understand how the runtime figured that out. Does the _type structure for Car contain a list of the names and signatures of every one of its methods, and then the interface-conversion code walks through that whole list at runtime to collect the needed methods to populate a Craft itab (or panic)?
In C++ terms, your Eface.(uint32) example is simply a std::any_cast — relatively cheap — but the vface.(Craft) example seems much wilder, much more dynamic and costly — so costly that it can't be done at all in C++. Is that right?