package main import ( "fmt" ) type Testinface interface { getLen(s string) (n int) } func strLen(strutil Testinface, content string) int { str_len := strutil.getLen(content) return str_len } type Mystra struct { str string } type Mystrb struct { num int } func (s Mystra) getLen(str string) int { fmt.Printf("caculating the str of struct : %v\n", s) return len(str) } func main() { mystra := Mystra{"test the interface"} mystrb := Mystrb{100} value := strLen(mystra, mystra.str) fmt.Println(value) //check the first parameter if it realize the Testinface interface when compiling value = strLen(mystrb, "teststr") }
./reflection.go:36: cannot use mystrb (type Mystrb) as type Testinface in argument to strLen: Mystrb does not implement Testinface (missing getLen method)
interface类型动态检测
不一定每次都使用静态的方法来检测接口的类型,也可以通过动态的方式进行检测,比如下面的例子:
package main import ( "fmt" "strconv" ) type Stringer interface { String() string } func ToString(any interface{}) string { if v, ok := any.(Stringer); ok { return v.String() } switch v := any.(type) { case int: return strconv.Itoa(v) case float64: return strconv.FormatFloat(v, 'f', -1, 64) } return "???" } func main() { value := ToString(123.345) fmt.Println(value) value = ToString(123456) fmt.Println(value) }
type Binary uint64 type myInt int type Stringer interface { String() string } func (i Binary) String() string { return strconv.Itoa(i.Get()) } func (i Binary) Get() int { return int(i) } func (i myInt) Get() int { return int(i) } func (i myInt) String() string { return strconv.Itoa(i.Get()) } func main() { b := Binary(20) s := Stringer(b) fmt.Println(reflect.TypeOf(s)) fmt.Println(reflect.TypeOf(s)) fmt.Println(reflect.TypeOf(new(Stringer))) fmt.Println(reflect.ValueOf(s)) var i interface{} fmt.Println(reflect.TypeOf(i)) i = b fmt.Println(reflect.TypeOf(i)) fmt.Println(reflect.ValueOf(i)) m := myInt(30) i = m fmt.Println(reflect.TypeOf(i)) fmt.Println(reflect.ValueOf(i)) fmt.Println(reflect.ValueOf(interface{}(s))) } /* output main.Binary main.Binary *main.Stringer 20 <nil> main.Binary 20 main.myInt 30 20 */
//show the basic function of type and value package main import ( "fmt" "reflect" ) func main() { var x string = "abc" fmt.Println("type:", reflect.TypeOf(x)) fmt.Println("value:", reflect.ValueOf(x)) fmt.Printf("value: %#v", reflect.ValueOf(x)) } /*output: type: string type: abc value: reflect.Value{typ:(*reflect.rtype)(0xa0820), ptr:(unsafe.Pointer)(0x20818a2c0), flag:0x58} */
// emptyInterface is the header for an interface{} value. type emptyInterface struct { typ *rtype word unsafe.Pointer } // nonEmptyInterface is the header for a interface value with methods. type nonEmptyInterface struct { // see ../runtime/iface.c:/Itab itab *struct { ityp *rtype // static interface type typ *rtype // dynamic concrete type link unsafe.Pointer bad int32 unused int32 fun [100000]unsafe.Pointer // method table } word unsafe.Pointer }
func TypeOf(i interface{}) Type { eface := *(*emptyInterface)(unsafe.Pointer(&i)) return toType(eface.typ) } func ValueOf(i interface{}) Value { if i == nil { return Value{} } // TODO(rsc): Eliminate this terrible hack. // In the call to unpackEface, i.typ doesn't escape, // and i.word is an integer. So it looks like // i doesn't escape. But really it does, // because i.word is actually a pointer. escapes(i) return unpackEface(i) }
package main import ( "fmt" "reflect" ) func main() { var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("type1:", v.Type()) fmt.Println("type2:", reflect.TypeOf(x)) fmt.Println("kind of x:", v.Kind()) fmt.Println("value of x:", v.Float()) type MyInt int var myint MyInt = 5 reflectv := reflect.ValueOf(myint) fmt.Println("type of myint: ", reflectv.Type()) fmt.Println("kind of myint: ", reflectv.Kind()) } /*output type1: float64 type2: float64 kind of x: float64 value of x: 3.4 type of myint: main.MyInt kind of myint: int */
package main import ( "fmt" "reflect" ) func main() { var x float32 = 32 v := reflect.ValueOf(x) fmt.Println("type:", v.Type()) fmt.Println("kind is uint8: ", v.Kind()) fmt.Println("the type:", reflect.TypeOf(v.Float())) fmt.Println("the type:", reflect.TypeOf(float32(v.Float()))) } /*output type: float32 kind is uint8: float32 the type: float64 the type: float32 */
再补充一点,在golang中可以使用断言的方式将接口类型的变量转化为具体data的类型,具体的语法如value, ok := interfaceInstance.(string),如果转化成功,value值与类型变为了具体的data的值与类型,否则ok的值就为false。从具体的某个底层类型转化为接口类型的实例,直接 newinterface:=InterfaceType(instance)即可转化成功。
// Interface returns v's current value as an interface{}. // It is equivalent to: // var i interface{} = (v's underlying value) // It panics if the Value was obtained by accessing // unexported struct fields. func (v Value) Interface() (i interface{}) { return valueInterface(v, true) }
package main import ( "fmt" "reflect" ) func main() { var x float64 = 3.4 v1 := reflect.ValueOf(x) fmt.Println("settability of v1:", v1.CanSet()) v2 := reflect.ValueOf(&x) fmt.Println("settability of v2:", v2.CanSet()) element := v2.Elem() fmt.Println("settability of element:", element.CanSet()) element.SetFloat(5.5) fmt.Println("the new value of v2:", element.Float()) } /*output settability of v1: false settability of v2: false settability of element: true the new value of v2: 5.5 */
// Elem returns the value that the interface v contains // or that the pointer v points to. // It panics if v's Kind is not Interface or Ptr. // It returns the zero Value if v is nil. func (v Value) Elem() Value {..}