Tags: #go
Rereference:
Under the hood, interface values can be thought of as a tuple of a value and a concrete type:
(value, type)
Calling a method on an interface value executes the method of the same name on its underlying type.
package main
import (
"fmt"
"math"
"reflect"
)
type I interface {
M()
}
type T struct {
S string
}
func (t *T) M() {
//fmt.Println(t.S)
}
type F float64
func (f F) M() {
//fmt.Println(f)
}
func main() {
var i I
i = &T{"Hello"}
describe(i) // &{S:Hello}, *main.T
i.M()
// &{S:Hello}, *main.T
fmt.Printf("%+v, %+v\n\n", reflect.ValueOf(i), reflect.TypeOf(i))
i = F(math.Pi)
describe(i) // 3.141592653589793, main.F
i.M()
// 3.141592653589793, main.F
fmt.Printf("%+v, %+v\n", reflect.ValueOf(i), reflect.TypeOf(i))
}
func describe(i I) {
fmt.Printf("%+v, %T\n", i, i)
}
When we assign to i
which is the interface I
, we’ll find that i
ultimately holds the expected value (e.g. either a struct T
or a float F
) but the ‘type’ associated with the i
variable isn’t actually the I
interface (which you might have expected) it’s actually the type of the value that was assigned.