编程语言
首页 > 编程语言> > Go语言(学习)——接口源码分析

Go语言(学习)——接口源码分析

作者:互联网

文章目录

描述接口的底层结构体

//以下源码在 runtime/runtime2.go 里
type iface struct {
	tab  *itab
	data unsafe.Pointer
}

type eface struct {
	_type *_type
	data  unsafe.Pointer
}
//以下源码在 runtime/runtime2.go 里
type itab struct {
	inter *interfacetype
	_type *_type
	hash  uint32 // copy of _type.hash. Used for type switches.
	_     [4]byte
	fun   [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}
//以下源码在 runtime/type.go 里
type interfacetype struct {
	typ     _type
	pkgpath name
	mhdr    []imethod
}
//以下源码在 runtime/type.go 里
type _type struct {
	size       uintptr
	ptrdata    uintptr // size of memory prefix holding all pointers
	hash       uint32
	tflag      tflag
	align      uint8
	fieldAlign uint8
	kind       uint8
	// function for comparing objects of this type
	// (ptr to object A, ptr to object B) -> ==?
	equal func(unsafe.Pointer, unsafe.Pointer) bool
	// gcdata stores the GC type data for the garbage collector.
	// If the KindGCProg bit is set in kind, gcdata is a GC program.
	// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
	gcdata    *byte
	str       nameOff
	ptrToThis typeOff
}
type maptype struct {
	typ    _type
	key    *_type
	elem   *_type
	bucket *_type // internal type representing a hash bucket
	// function for hashing keys (ptr to key, seed) -> hash
	hasher     func(unsafe.Pointer, uintptr) uintptr
	keysize    uint8  // size of key slot
	elemsize   uint8  // size of elem slot
	bucketsize uint16 // size of bucket
	flags      uint32
}

type arraytype struct {
	typ   _type
	elem  *_type
	slice *_type
	len   uintptr
}

type chantype struct {
	typ  _type
	elem *_type
	dir  uintptr
}

type slicetype struct {
	typ  _type
	elem *_type
}

type functype struct {
	typ      _type
	inCount  uint16
	outCount uint16
}

type ptrtype struct {
	typ  _type
	elem *_type
}

图示接口的底层结构体全貌

接口的动态类型和动态值

接口类型和 nil 作比较

package main

import "fmt"

type coder interface {
	code()
	debug()
}

type Gopher struct {
	language string
}

func (g Gopher)code() {
	fmt.Printf("I am coding %s language.\n", g.language)
}

func (g *Gopher)debug() {
	g.language = "golang"
	fmt.Printf("I am debugging %s language.\n", g.language)
}

func main() {
	var c coder
	fmt.Printf("before 'c=g', interface: coder %T, %v\n", c, c)
	fmt.Println("before 'c=g', c == nil:", c == nil)

	var g *Gopher
	c = g
	fmt.Println("g == nil:", g == nil)
	fmt.Printf("after 'c=g', interface: coder %T, %v\n", c, c)
	fmt.Println("after 'c=g', c == nil:", c == nil)
}
before 'c=g', interface: coder <nil>, <nil>
before 'c=g', c == nil: true
g == nil: true
after 'c=g', interface: coder *Gopher, <nil>
after 'c=g', c == nil: false
package main

import "fmt"

type Myerror struct {
	err string
}

func (m Myerror) Error() string {
	return m.err
}

func passError() error { //error是接口
	var myerror *Myerror = nil
	return myerror
}

func main() {
	err := passError()
	fmt.Println(err)
	fmt.Println(err == nil)
	fmt.Printf("%T, %v\n", err, err)
}
<nil>
false
*Myerror, <nil>

打印接口的动态类型和值

package main

import (
	"unsafe"
	"fmt"
)

type iface struct {
	itab, data uintptr
}

func main() {
	var a interface{} = nil

	var b interface{} = (*int)(nil)

	x := 5
	var c interface{} = (*int)(&x)
	
	ia := *(*iface)(unsafe.Pointer(&a))
	ib := *(*iface)(unsafe.Pointer(&b))
	ic := *(*iface)(unsafe.Pointer(&c))

	fmt.Println(ia, ib, ic)

	fmt.Println(*(*int)(unsafe.Pointer(ic.data)))
}
{0 0} {4881696 0} {4881696 824634236592}
5

打印接口的hash值

package main

import (
	"fmt"
	"unsafe"
)

type Monster interface {
	Beat()
}

type Gesila struct {
	weight string
}

func (g Gesila) Beat() {
	fmt.Println("哥斯拉发出原子吐息!")
}

type itab struct {
	inter uintptr
	_type uintptr
	hash  uint32
	_     [4]byte
	fun   [1]uintptr
}

type iface struct {
	tab *Itab
	data uintptr
}

func main() {
	var m Monster = Monster(Gesila{weight: "12万吨"})
	r := *(*iface)(unsafe.Pointer(&m))
	fmt.Println(r.tab.hash)
}
3308854674

标签:iface,struct,nil,fmt,接口,源码,Go,type
来源: https://blog.csdn.net/wxy_csdn_world/article/details/115559131