package mainimport"fmt"type User struct{id intname string}funcmain(){u := User{1,"Tom"}var i interface{}= uu.id =2u.name ="Jack"fmt.Printf("%v\n", u)fmt.Printf("%v\n", i.(User))}
接口转型返回临时对象,只有使用指针才能修改其状态
package mainimport"fmt"type User struct{id intname string}funcmain(){u := User{1,"Tom"}var vi, pi interface{}= u,&u// vi.(User).name = "Jack" // Error: cannot assign to vi.(User).namepi.(*User).name ="Jack"fmt.Printf("%v\n", vi.(User))fmt.Printf("%v\n", pi.(*User))}
只有 tab 和 data 都为 nil 时,接口才等于 nil。
var a interface{}=nil// tab = nil, data = nilvar b interface{}=(*int)(nil)// tab 包含 *int 类型信息, data = niltype iface struct{itab, data uintptr}ia :=*(*iface)(unsafe.Pointer(&a))
ib :=*(*iface)(unsafe.Pointer(&b))fmt.Println(a ==nil, ia)
fmt.Println(b ==nil, ib, reflect.ValueOf(b).IsNil())//输出:true{00}false{5057280}true
2. 接口转换
2.1 利用类型推断,可判断接口对象是否某个具体的接口或类型。
type User struct{id intname string}func(self *User)String()string{return fmt.Sprintf("%d, %s", self.id, self.name)}funcmain(){var o interface{}=&User{1,"Tom"}if i, ok := o.(fmt.Stringer); ok {// ok-idiomfmt.Println(i)}u := o.(*User)// u := o.(User) // panic: interface is *main.User, not main.Userfmt.Println(u)}
2.2 还可用 switch 做批量类型判断,不支持 fallthrough。
funcmain(){var o interface{}=&User{1,"Tom"}switch v := o.(type){casenil:// o == nilfmt.Println("nil")case fmt.Stringer:// interfacefmt.Println(v)casefunc()string:// funcfmt.Println(v())case*User:// *structfmt.Printf("%d, %s\n", v.id, v.name)default:fmt.Println("unknown")}}
2.3 超集接口对象可转换为子集接口,反之出错。
type Stringer interface{String()string}type Printer interface{String()stringPrint()}type User struct{id intname string}func(self *User)String()string{return fmt.Sprintf("%d, %v", self.id, self.name)}func(self *User)Print(){fmt.Println(self.String())}funcmain(){var o Printer =&User{1,"Tom"}var s Stringer = ofmt.Println(s.String())}