// src/runtime/type.go // ptrType represents a pointer type. type ptrType struct { typ _type // 指针类型 elem *_type // 指针所指向的元素类型 } type chantype struct { typ _type // channel类型 elem *_type // channel元素类型 dir uintptr } type maptype struct { typ _type key *_type elem *_type bucket *_type // internal type representing a hash bucket hmap *_type // internal type representing a hmap keysize uint8// size of key slot indirectkey bool// store ptr to key instead of key itself valuesize uint8// size of value slot indirectvalue bool// store ptr to value instead of value itself bucketsize uint16// size of bucket reflexivekey bool// true if k==k for all keys needkeyupdate bool// true if we need to update key on an overwrite }
// runtime/runtime2.go // 非空接口 type iface struct { tab *itab data unsafe.Pointer }
// 非空接口的类型信息 type itab struct { inter *interfacetype // 接口定义的类型信息 _type *_type // 接口实际指向值的类型信息 link *itab bad int32 inhash int32 fun [1]uintptr// 接口方法实现列表,即函数地址列表,按字典序排序 }
// runtime/type.go // 非空接口类型,接口定义,包路径等。 type interfacetype struct { typ _type pkgpath name mhdr []imethod // 接口方法声明列表,按字典序排序 }
// 接口的方法声明 type imethod struct { name nameOff // 方法名 ityp typeOff // 描述方法参数返回值等细节 }
var ( ifaceLock mutex // lock for accessing hash hash [hashSize]*itab ) // 简单的Hash算法 funcitabhash(inter *interfacetype, typ *_type)uint32 { h := inter.typ.hash h += 17 * typ.hash return h % hashSize }
// 根据interface_type和concrete_type获取或生成itab信息 funcgetitab(inter *interfacetype, typ *_type, canfail bool) *itab { ... // 算出hash key h := itabhash(inter, typ)
var m *itab ... // 遍历hash slot链表 for m = (*itab)(atomic.Loadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link { // 如果在hash表中找到则返回 if m.inter == inter && m._type == typ { if m.bad { if !canfail { additab(m, locked != 0, false) } m = nil } ... return m } } } // 如果没有找到,则尝试生成itab(会检查是否满足接口) m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys)) m.inter = inter m._type = typ additab(m, true, canfail) if m.bad { returnnil } return m }
// 检查concrete_type是否符合interface_type 并且创建对应的itab结构体 将其放到hash表中 funcadditab(m *itab, locked, canfail bool) { inter := m.inter typ := m._type x := typ.uncommon()
ni := len(inter.mhdr) nt := int(x.mcount) xmhdr := (*[1 << 16]method)(add(unsafe.Pointer(x), uintptr(x.moff)))[:nt:nt] j := 0 for k := 0; k < ni; k++ { i := &inter.mhdr[k] itype := inter.typ.typeOff(i.ityp) name := inter.typ.nameOff(i.name) iname := name.name() ipkg := name.pkgPath() if ipkg == "" { ipkg = inter.pkgpath.name() } for ; j < nt; j++ { t := &xmhdr[j] tname := typ.nameOff(t.name) // 检查方法名字是否一致 if typ.typeOff(t.mtyp) == itype && tname.name() == iname { pkgPath := tname.pkgPath() if pkgPath == "" { pkgPath = typ.nameOff(x.pkgpath).name() } // 是否导出或在同一个包 if tname.isExported() || pkgPath == ipkg { if m != nil { // 获取函数地址,并加入到itab.fun数组中 ifn := typ.textOff(t.ifn) *(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = ifn } goto nextimethod } } } // didn't find method if !canfail { if locked { unlock(&ifaceLock) } panic(&TypeAssertionError{"", typ.string(), inter.typ.string(), iname}) } m.bad = true break nextimethod: } if !locked { throw("invalid itab locking") } // 加到Hash Slot链表中 h := itabhash(inter, typ) m.link = hash[h] m.inhash = true atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m)) }
type MyStruct struct{} func(ms MyStruct)Print() {}
funcmain() { a := 1 b := "str" c := MyStruct{} var i1 interface{} = a var i2 interface{} = b var i3 MyInterface = c var i4 interface{} = i3 var i5 = i4.(MyInterface) fmt.Println(i1, i2, i3, i4, i5) }
// go1.8/src/runtime/iface.go funcconvT2E(t *_type, elem unsafe.Pointer)(e eface) { if raceenabled { raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E)) } if msanenabled { msanread(elem, t.size) } if isDirectIface(t) { // This case is implemented directly by the compiler. throw("direct convT2E") } x := newobject(t) // TODO: We allocate a zeroed object only to overwrite it with // actual data. Figure out how to avoid zeroing. Also below in convT2I. typedmemmove(t, x, elem) e._type = t e.data = x return }
funcconvT2I(tab *itab, elem unsafe.Pointer)(i iface) { t := tab._type if raceenabled { raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I)) } if msanenabled { msanread(elem, t.size) } if isDirectIface(t) { // This case is implemented directly by the compiler. throw("direct convT2I") } x := newobject(t) typedmemmove(t, x, elem) i.tab = tab i.data = x return }
funcassertE2I(inter *interfacetype, e eface)(r iface) { t := e._type if t == nil { // explicit conversions require non-nil interface value. panic(&TypeAssertionError{"", "", inter.typ.string(), ""}) } r.tab = getitab(inter, t, false) r.data = e.data return }
type Value struct { // 值的类型 typ *rtype // 立即数或指向数据的指针 ptr unsafe.Pointer // type flag uintptr // 指明值的类型,是否只读,ptr字段是否是指针等 flag }
func ValueOf(i interface{}) Value { if i == nil { return Value{} }
escapes(i)
return unpackEface(i) }
// 将数据从interface{}解包为reflec.Value func unpackEface(i interface{}) Value { e := (*emptyInterface)(unsafe.Pointer(&i)) // NOTE: don't read e.word until we know whether it is really a pointer or not. t := e.typ if t == nil { return Value{} } f := flag(t.Kind()) if ifaceIndir(t) { f |= flagIndir } return Value{t, e.word, f} } // 将数据由reflect.Value打包为interface{} func packEface(v Value) interface{} { t := v.typ var i interface{} e := (*emptyInterface)(unsafe.Pointer(&i)) // First, fill in the data portion of the interface. switch { case ifaceIndir(t): if v.flag&flagIndir == 0 { panic("bad indir") } ptr := v.ptr if v.flag&flagAddr != 0 { c := unsafe_New(t) typedmemmove(t, c, ptr) ptr = c } e.word = ptr case v.flag&flagIndir != 0: e.word = *(*unsafe.Pointer)(v.ptr) default: e.word = v.ptr }
e.typ = t return i } // 将reflect.Value转换为interface{},相当于reflect.ValueOf的逆操作 // 等价于: var i interface{} = (v's underlying value) func (v Value) Interface() (i interface{}) { return valueInterface(v, true) }
func valueInterface(v Value, safe bool) interface{} { if v.flag == 0 { panic(&ValueError{"reflect.Value.Interface", 0}) } if safe && v.flag&flagRO != 0 { panic("reflect.Value.Interface: cannot return value obtained from unexported field or method") } if v.flag&flagMethod != 0 { v = makeMethodValue("Interface", v) } // 当interface{}作为子类型时,会产生类型为Interface的Value // 如 reflect.TypeOf(m).Elem().Kind() == Interface if v.kind() == Interface { if v.NumMethod() == 0 { return *(*interface{})(v.ptr) } return *(*interface { M() })(v.ptr) } return packEface(v) }
// reflect/value.go // New returns a Value representing a pointer to a new zero value // for the specified type. That is, the returned Value's Type is PtrTo(typ). funcNew(typ Type)Value { if typ == nil { panic("reflect: New(nil)") } ptr := unsafe_New(typ.(*rtype)) fl := flag(Ptr) return Value{typ.common().ptrTo(), ptr, fl} } // runtime/malloc.go funcnewobject(typ *_type)unsafe.Pointer { return mallocgc(typ.size, typ, true) }