go源码阅读——type.go

Posted Wang-Junchao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go源码阅读——type.go相关的知识,希望对你有一定的参考价值。

【博文目录>>>】 【项目地址>>>】


基本结构图

reflect包基础类型是Type,其主要实现是rtype,在rtype下会有基于种类型的实现,主要结构图。

基本常量

数据类型常量

type Kind uint

const (
	Invalid Kind = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	Array
	Chan
	Func
	Interface
	Map
	Ptr
	Slice
	String
	Struct
	UnsafePointer
)


// 包reflect实现了运行时反射,从而允许程序处理任意类型的对象。典型的用法是使用静态类型
// interface获取一个值,并通过调用TypeOf来提取其动态类型信息,它返回一个Type类型。
// Package reflect implements run-time reflection, allowing a program to
// manipulate objects with arbitrary types. The typical use is to take a value
// with static type interface and extract its dynamic type information by
// calling TypeOf, which returns a Type.
//
// 调用ValueOf返回一个代表运行时数据的Value。
// Zero也是一种类型,并返回一个表示该类型的零值。
// A call to ValueOf returns a Value representing the run-time data.
// Zero takes a Type and returns a Value representing a zero value
// for that type.
//
// 有关Go语言中反射的介绍,请参见“反射规则”:https://golang.org/doc/articles/laws_of_reflection.html
// See "The Laws of Reflection" for an introduction to reflection in Go:
// https://golang.org/doc/articles/laws_of_reflection.html
package reflect

import (
	"strconv"
	"sync"
	"unicode"
	"unicode/utf8"
	"unsafe"
)

// Type是Go类型的表示。
//
// 并非所有方法都适用于所有类型。在每种方法的限制都在文档中注明了(如果有)。
// 在调用特定于种类的方法之前,使用Kind方法找出类型。调用不适合该类型的方法会导致运行时恐慌。
//
// 类型值是可比较的,例如==运算符,因此它们可用作映射键。
// 如果两个Type值表示相同的类型,则它们相等
// Type is the representation of a Go type.
//
// Not all methods apply to all kinds of types. Restrictions,
// if any, are noted in the documentation for each method.
// Use the Kind method to find out the kind of type before
// calling kind-specific methods. Calling a method
// inappropriate to the kind of type causes a run-time panic.
//
// Type values are comparable, such as with the == operator,
// so they can be used as map keys.
// Two Type values are equal if they represent identical types.
type Type interface 
    // 适用于所有类型的方法。
	// Methods applicable to all types.

    // 当在内存中分配时,Align返回此类型的值的对齐方式(以字节为单位)。
	// Align returns the alignment in bytes of a value of
	// this type when allocated in memory.
	/**
	 * @return Question: 返回值代表什么?
	 * @date 2020-03-15 19:43:54
	 **/
	Align() int

    // 当用作结构体中的字段时,FieldAlign返回此类型值的对齐方式(以字节为单位)。
	// FieldAlign returns the alignment in bytes of a value of
	// this type when used as a field in a struct.
	/**
	 * @return
	 * @date 2020-03-15 19:45:52
	 **/
	FieldAlign() int

    // 方法返回类型的方法集中的第i个方法。如果i不在[0,NumMethod())范围内,引发恐慌。
    //
    // 对于非接口类型T或*T,返回的Method的Type和Func字段描述了一个函数,其第一个参数为接收者。
    //
    // 对于接口类型,返回的Method的Type字段给出方法签名,没有接收者,并且Func字段为nil。
    //
    // 仅可访问导出的方法,并且它们按字典顺序排序
	// Method returns the i'th method in the type's method set.
	// It panics if i is not in the range [0, NumMethod()).
	//
	// For a non-interface type T or *T, the returned Method's Type and Func
	// fields describe a function whose first argument is the receiver.
	//
	// For an interface type, the returned Method's Type field gives the
	// method signature, without a receiver, and the Func field is nil.
	//
	// Only exported methods are accessible and they are sorted in
	// lexicographic order.
	/**
	 * @param 第i个方法
	 * @return 方法描述信息
	 * @date 2020-03-15 19:49:07
	 **/
	Method(int) Method

    // MethodByName返回在类型的方法集中具有该名称的方法,以及一个布尔值,指示是否找到该方法。
    //
    // 对于非接口类型T或*T,返回的Method的Type和Func字段描述了一个函数,其第一个参数为接收者。
    //
    // 对于接口类型,返回的Method的Type字段给出了方法签名,没有接收者,而Func字段为nil
    //
	// MethodByName returns the method with that name in the type's
	// method set and a boolean indicating if the method was found.
	//
	// For a non-interface type T or *T, the returned Method's Type and Func
	// fields describe a function whose first argument is the receiver.
	//
	// For an interface type, the returned Method's Type field gives the
	// method signature, without a receiver, and the Func field is nil.
	/**
	 * @param string 方法名
	 * @return Method 方法结构体
	 * @return bool true: 表示找到
	 * @date 2020-03-16 14:04:12
	 **/
	MethodByName(string) (Method, bool)

	// NumMethod returns the number of exported methods in the type's method set.
	/**
	 * NumMethod返回类型的方法集中导出的方法的数量。
	 * @return int 方法集中导出的方法的数量
	 * @date 2020-03-16 17:02:19
	 **/
	NumMethod() int

	// Name returns the type's name within its package for a defined type.
	// For other (non-defined) types it returns the empty string.
	/**
	 * Name返回其包中已定义类型的类型名称。 对于其他(未定义)类型,它返回空字符串。
	 * @return string 包中已定义类型的类型名称
	 * @date 2020-03-16 17:04:06
	 **/
	Name() string

	// PkgPath returns a defined type's package path, that is, the import path
	// that uniquely identifies the package, such as "encoding/base64".
	// If the type was predeclared (string, error) or not defined (*T, struct,
	// []int, or A where A is an alias for a non-defined type), the package path
	// will be the empty string.
	/**
	 * PkgPath返回定义的类型的包路径,即唯一标识包的导入路径,例如"encoding/base64"。
     * 如果类型是预先声明的(字符串,错误)或未定义(*T,struct,[]int或A,其中A是未定义类型的别名),则包路径将为空字符串。
	 * @return string 回定义的类型的包路径
	 * @date 2020-03-16 17:04:49
	 **/
	PkgPath() string

	// Size returns the number of bytes needed to store
	// a value of the given type; it is analogous to unsafe.Sizeof.
	/**
	 * Size返回存储给定类型的值所需的字节数;它类似于unsafe.Sizeof。
	 * @return uintptr 存储给定类型的值所需的字节数
	 * @date 2020-03-16 17:06:39
	 **/
	Size() uintptr

	// String returns a string representation of the type.
	// The string representation may use shortened package names
	// (e.g., base64 instead of "encoding/base64") and is not
	// guaranteed to be unique among types. To test for type identity,
	// compare the Types directly.
	/**
	 * String返回该类型的字符串表示形式。字符串表示形式可以使用缩短的包名称(例如,使用base64代替"encoding/base64"),
	 * 并且不能保证类型之间的唯一性。要测试类型标识,请直接比较类型。
	 * @return string 类型的字符串表示形式
	 * @date 2020-03-16 17:07:52
	 **/
	String() string

	// Kind returns the specific kind of this type.
	/**
	 * Kind返回此类型的特定类型。
	 * @return Kind 此类型的特定类型
	 * @date 2020-03-16 17:08:43
	 **/
	Kind() Kind

	// Implements reports whether the type implements the interface type u.
	/**
	 * 实现报告类型是否实现接口类型u。
	 * @param u 接口类型
	 * @return true: 实现了接口类型u
	 * @date 2020-03-16 17:09:43
	 **/
	Implements(u Type) bool

	// AssignableTo reports whether a value of the type is assignable to type u.
	/**
	 * AssignableTo报告类型的值是否可分配给类型u。
	 * @param u 任意类型
	 * @return true: 类型的值是可分配给类型u
	 * @date 2020-03-16 17:10:28
	 **/
	AssignableTo(u Type) bool

	// ConvertibleTo reports whether a value of the type is convertible to type u.
	/**
	 * ConvertibleTo报告该类型的值是否可转换为u类型。
	 * @param u 任意类型
	 * @return 类型的值是否可转换为u类型。
	 * @date 2020-03-16 17:11:44
	 **/
	ConvertibleTo(u Type) bool

	// Comparable reports whether values of this type are comparable.
	/**
	 * Comparable较报告此类型的值是否可比较。
	 * @return true 此类型的值是可比较
	 * @date 2020-03-16 17:12:22
	 **/
	Comparable() bool

    /**
     * 方法仅适用于某些类型,具体取决于种类。每种类型允许使用的方法是:
     * Int*, Uint*, Float*, Complex*: Bits
     * Array: Elem, Len
     * Chan: ChanDir, Elem
     * Func: In, NumIn, Out, NumOut, IsVariadic.
     * Map: Key, Elem
     * Ptr: Elem
     * Slice: Elem
     * Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField
     **/
	// Methods applicable only to some types, depending on Kind.
	// The methods allowed for each kind are:
	//
	//	Int*, Uint*, Float*, Complex*: Bits
	//	Array: Elem, Len
	//	Chan: ChanDir, Elem
	//	Func: In, NumIn, Out, NumOut, IsVariadic.
	//	Map: Key, Elem
	//	Ptr: Elem
	//	Slice: Elem
	//	Struct: Field, FieldByIndex, FieldByName, FieldByNameFunc, NumField

	// Bits returns the size of the type in bits.
	// It panics if the type's Kind is not one of the
	// sized or unsized Int, Uint, Float, or Complex kinds.
	/**
	 * Bits返回以位为单位的类型的大小。 如果类型的Kind不是大小或大小不完整的Int,Uint,Float或Complex类型之一,它就会感到恐慌。
	 * @return 位为单位的类型的大小
	 * @date 2020-03-16 17:16:37
	 **/
	Bits() int

	// ChanDir returns a channel type's direction.
	// It panics if the type's Kind is not Chan.
	/**
	 * ChanDir返回通道类型的方向。如果类型的种类不是Chan,则会引起恐慌。
	 * @return 通道类型的方向
	 * @date 2020-03-17 08:05:51
	 **/
	ChanDir() ChanDir

	// IsVariadic reports whether a function type's final input parameter
	// is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's
	// implicit actual type []T.
	//
	// For concreteness, if t represents func(x int, y ... float64), then
	//
	//	t.NumIn() == 2
	//	t.In(0) is the reflect.Type for "int"
	//	t.In(1) is the reflect.Type for "[]float64"
	//	t.IsVariadic() == true
	//
	// IsVariadic panics if the type's Kind is not Func.
	/**
	 * IsVariadic报告函数类型的最终输入参数是否为“...”参数。如果是这样,则t.In(t.NumIn()-1)返回参数的隐式实际类型[]T。
     *
     * 具体来说,如果t代表func(x int,y ... float64),则
     *
     * t.NumIn()== 2
     * t.In(0)是“ int”的reflect.Type
     * t.In(1)是“ [] float64”的reflect.Type
     * t.IsVariadic()== true
     *
     * 如果类型的Kind不是Func,则为IsVariadic恐慌。
	 * @return 是否是可变参数类型,true:是
	 * @date 2020-03-17 08:09:56
	 **/
	IsVariadic() bool

	// Elem returns a type's element type.
	// It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
	/**
	 * Elem返回类型的元素类型。如果类型的Kind不是Array,Chan,Map,Ptr或Slice,它会感到恐慌。
	 * @return 元素类型
	 * @date 2020-03-17 08:12:23
	 **/
	Elem() Type

	// Field returns a struct type's i'th field.
	// It panics if the type's Kind is not Struct.
	// It panics if i is not in the range [0, NumField()).
	/**
	 * Field返回结构类型的第i个字段。如果类型的Kind不是Struct,它会感到恐慌。如果i不在[0,NumField())范围内,它引起恐慌。
	 * @param i 第i个字段
	 * @return 结体字段类型
	 * @date 2020-03-17 08:13:06
	 **/
	Field(i int) StructField

	// FieldByIndex returns the nested field corresponding
	// to the index sequence. It is equivalent to calling Field
	// successively for each index i.
	// It panics if the type's Kind is not Struct.
	/**
	 * FieldByIndex返回与索引序列相对应的嵌套字段。等效于为每个索引i依次调用Field。如果类型的Kind不是Struct,它会引起恐慌。
	 * @param index 字段索引数组
	 * @return 结体字段类型
	 * @date 2020-03-17 08:15:36
	 **/
	FieldByIndex(index []int) StructField

	// FieldByName returns the struct field with the given name
	// and a boolean indicating if the field was found.
	/**
	 * FieldByName返回具有给定名称的struct字段和一个布尔值,指示是否找到了该字段。
	 * @param name 字符段名称
	 * @return StructField 结体字段类型
	 * @return bool true: 找到了该字段。false:否
	 * @date 2020-03-17 08:16:43
	 **/
	FieldByName(name string) (StructField, bool)

	// FieldByNameFunc returns the struct field with a name
	// that satisfies the match function and a boolean indicating if
	// the field was found.
	//
	// FieldByNameFunc considers the fields in the struct itself
	// and then the fields in any embedded structs, in breadth first order,
	// stopping at the shallowest nesting depth containing one or more
	// fields satisfying the match function. If multiple fields at that depth
	// satisfy the match function, they cancel each other
	// and FieldByNameFunc returns no match.
	// This behavior mirrors Go's handling of name lookup in
	// structs containing embedded fields.
	/**
	 * FieldByNameFunc返回具有满足match函数名称的struct字段和一个布尔值,指示是否找到该字段。
     *
     * FieldByNameFunc会先考虑结构本身中的字段,然后再考虑所有嵌入式结构中的字段,并以广度优先
     * 的顺序停在最浅的嵌套深度,其中包含一个或多个满足match函数的字段。如果该深度处的多个字段满
     * 足匹配功能,则它们会相互取消,并且FieldByNameFunc不返回匹配项。此行为反映了Go在包含嵌入
     * 式字段的结构中对名称查找的处理。
	 * @param match 根据名称进行匹配的函数
	 * @return StructField 结体字段类型
	 * @return bool true: 找到了该字段。false:否
	 * @date 2020-03-17 08:21:04
	 **/
	FieldByNameFunc(match func(string) bool) (StructField, bool)

	// In returns the type of a function type's i'th input parameter.
	// It panics if the type's Kind is not Func.
	// It panics if i is not in the range [0, NumIn()).
	/**
	 * In返回函数类型的第i个输入参数的类型。如果类型的Kind不是Func,它会感到恐慌。如果i不在[0, NumIn())范围内,它将发生恐慌。
	 * @param i 第i个参数
	 * @return 参数的类型
	 * @date 2020-03-17 08:24:45
	 **/
	In(i int) Type

	// Key returns a map type's key type.
	// It panics if the type's Kind is not Map.
	/**
	 * Key返回Map类型的键类型。如果类型的Kind不是Map,则会发生恐慌。
	 * @return 键类型
	 * @date 2020-03-17 08:26:07
	 **/
	Key() Type

	// Len returns an array type's length.
	// It panics if the type's Kind is not Array.
	/**
	 * Len返回数组类型的长度。如果类型的Kind不是Array,它会惊慌。
	 * @return 数组类型的长度
	 * @date 2020-03-17 08:27:12
	 **/
	Len() int

	// NumField returns a struct type's field count.
	// It panics if the type's Kind is not Struct.
	/**
	 * NumField返回结构类型的字段数。如果类型的Kind不是Struct,它会引起恐慌。
	 * @return 类型的字段数
	 * @date 2020-03-17 08:29:50
	 **/
	NumField() int

	// NumIn returns a function type's input parameter count.
	// It panics if the type's Kind is not Func.
	/**
	 * NumIn返回函数类型的输入参数个数。如果类型的Kind不是Func,它会引起恐慌。
	 * @return 输入参数个数
	 * @date 2020-03-17 08:30:48
	 **/
	NumIn() int

	// NumOut returns a function type's output parameter count.
	// It panics if the type's Kind is not Func.
    /**
	 * NumIn返回函数类型的输出参数个数。如果类型的Kind不是Func,它会引起恐慌。
	 * @return 输出参数个数
	 * @date 2020-03-17 08:30:48
	 **/
	NumOut() int

	// Out returns the type of a function type's i'th output parameter.
	// It panics if the type's Kind is not Func.
	// It panics if i is not in the range [0, NumOut()).
	/**
	 * Out返回函数类型的第i个输出参数的类型。如果类型的Kind不是Func,它会引起恐慌。如果我不在[0, NumOut())范围内,它会引起恐慌。
	 * @param 第i个输出参数
	 * @return 第i个输出参数类型
	 * @date 2020-03-17 08:32:49
	 **/
	Out(i int) Type
    
    /**
     * 此方法获取大多数值的一些通用实现
     * @return *rtype rtype是大多数值的通用实现。它嵌入在其他结构类型中。
     * @date 2020-03-17 08:35:18 
     **/
	common() *rtype
	/**
	 * 此方法获取值的非通用实现
	 * @return *uncommonType uncommonType仅对于定义的类型或带有方法的类型存在
	 * @date 2020-03-17 08:36:42 
	 **/
	uncommon() *uncommonType


/**
 * BUG(rsc):FieldByName和相关函数将结构字段名称视为相等,即使名称相同,即使它们是源自不同包的未导出名称也是如此。
 * 这样做的实际效果是,如果结构类型t包含多个名为x的字段(从不同的程序包中嵌入的),则t.FieldByName("x")的结果定义不明确。
 * FieldByName可能返回名为x的字段之一,或者可能报告没有字段。有关更多详细信息,请参见https://golang.org/issue/4876。
 * 示例:https://play.golang.org/p/WTj5d06CQ3
 **/
// BUG(rsc): FieldByName and related functions consider struct field names to be equal
// if the names are equal, even if they are unexported names originating
// in different packages. The practical effect of this is that the result of
// t.FieldByName("x") is not well defined if the struct type t contains
// multiple fields named x (embedded from different packages).
// FieldByName may return one of the fields named x or may report that there are none.
// See https://golang.org/issue/4876 for more details.

/**
 * 这些数据结构是编译器已知的(../../cmd/internal/gc/reflect.go)。
 * 少部分被../runtime/type.go已知并且传递给调试器。
 * 他们都被../runtime/type.go已知
 *
 */
/*
 * These data structures are known to the compiler (../../cmd/internal/gc/reflect.go).
 * A few are known to ../runtime/type.go to convey to debuggers.
 * They are also known to ../runtime/type.go.
 */

/**
 * Kind代表类型所代表的特定类型的种类。零种类不是有效种类。
 **/
// A Kind represents the specific kind of type that a Type represents.
// The zero Kind is not a valid kind.
type Kind uint

const (
	Invalid Kind = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	Array
	Chan
	Func
	Interface
	Map
	Ptr
	Slice
	String
	Struct
	UnsafePointer
)

// tflag is used by an rtype to signal what extra type information is
// available in the memory directly following the rtype value.
//
// tflag values must be kept in sync with copies in:
//	cmd/compile/internal/gc/reflect.go
//	cmd/link/internal/ld/decodesym.go
//	runtime/type.go
/**
 * rtype使用tflag来指示紧随rtype值之后在内存中还有哪些额外的类型信息。
 *
 * tflag值必须与以下副本保持同步:
 * cmd/compile/internal/gc/reflect.go
 * cmd/link/internal/ld/decodesym.go
 * runtime/type.go
 **/
type tflag uint8

const (
	// tflagUncommon means that there is a pointer, *uncommonType,
	// just beyond the outer type structure.
	//
	// For example, if t.Kind() == Struct and t.tflag&tflagUncommon != 0,
	// then t has uncommonType data and it can be accessed as:
	//
	//	type tUncommon struct 
	//		structType
	//		u uncommonType
	//	
	//	u := &(*tUncommon)(unsafe.Pointer(t)).u
	/**
	 * tflagUncommon意味着在外部类型结构之后,还有一个指针* uncommonType。
     *
     * 例如,如果t.Kind()== Struct且t.tflag&tflagUncommon != 0,则t具有uncommonType数据,可以按以下方式访问它:
     *  type tUncommon struct 
     *      structType
     *      u uncommonType
     *  
     *  u := &(*tUncommon)(unsafe.Pointer(t)).u
	 **/
	tflagUncommon tflag = 1 << 0 // 0x00000001 = 1

	// tflagExtraStar means the name in the str field has an
	// extraneous '*' prefix. This is because for most types T in
	// a program, the type *T also exists and reusing the str data
	// saves binary size.
	/**
	 * tflagExtraStar表示str字段中的名称带有多余的“*”前缀。这是因为对于程序中的大多数T类型,
	 * T类型也存在,并且重新使用str数据可节省二进制大小。
	 **/
	tflagExtraStar tflag = 1 << 1 // 0x00000010 = 2

	// tflagNamed means the type has a name.
	/**
	 * tflagNamed表示类型具有名称。
	 **/
	tflagNamed tflag = 1 << 2 // 0x00000100 = 4

	// tflagRegularMemory means that equal and hash functions can treat
	// this type as a single region of t.size bytes.
	/**
	 * tflagRegularMemory意味着equal和hash函数可以将此类型视为t.size字节的单个区域。
	 **/
	tflagRegularMemory tflag = 1 << 3 // 0x00001000 = 8
)

// rtype is the common implementation of most values.
// It is embedded in other struct types.
//
// rtype must be kept in sync with ../runtime/type.go:/^type._type.
/**
 * rtype是大多数值的通用实现。
 * 它嵌入在其他结构类型中。
 *
 * rtype必须与../runtime/type.go:/^type._type保持同步。
 **/
type rtype struct 
	size       uintptr
	ptrdata    uintptr // number of bytes in the type that can contain pointers // 包含指针的类型需要的字节数
	hash       uint32  // hash of type; avoids computation in hash tables // 类型的哈希避免在哈希表中进行计算
	tflag      tflag   // extra type information flags // 额外类型信息标志
	align      uint8   // alignment of variable with this type // 变量与此类型的对齐 Question: 都有哪些值代表什么
	fieldAlign uint8   // alignment of struct field with this type // 结构体字段与此类型的对齐 Question: 都有哪些值代表什么
	kind       uint8   // enumeration for C // C的枚举 Question: 都有哪些值代表什么
	// 比较此类型的比较函数
	// function for comparing objects of this type
	// (ptr to object A, ptr to object B) -> ==?
	equal     func(unsafe.Pointer, unsafe.Pointer) bool
	gcdata    *byte   // garbage collection data // 垃圾收集数据 Question: 会有一些什么样子的数据
	str       nameOff // string form // 字符串形式 Question: 有哪些字符串形式
	ptrToThis typeOff // type for pointer to this type, may be zero // 指向此类型的指针的类型,可以为零


// Method on non-interface type
/**
 * 非接口类型的方法
 **/
type method struct 
	name nameOff // name of method // 方法名
	mtyp typeOff // method type (without receiver) // 方法类型(无接收者)
	ifn  textOff // fn used in interface call (one-word receiver) // 接口调用中使用的fn(单字接收器)
	tfn  textOff // fn used for normal method call // fn用于普通方法调用


// uncommonType is present only for defined types or types with methods
// (if T is a defined type, the uncommonTypes for T and *T have methods).
// Using a pointer to this struct reduces the overall size required
// to describe a non-defined type with no methods.
/**
 * uncommonType仅对定义的类型或带有方法的类型存在(如果T是定义的类型,则T和*T的uncommonTypes具有方法)。
 * 使用指向此结构的指针可减少描述没有方法的未定义类型所需的总体大小。
 **/
type uncommonType struct 
	pkgPath nameOff // import path; empty for built-in types like int, string // 导入路径;对于内置类型(如int,string)为空
	mcount  uint16  // number of methods // 方法数量
	xcount  uint16  // number of exported methods // 导出的方法数量
	moff    uint32  // offset from this uncommontype to [mcount]method // 从uncommontype到[mcount]method偏移量
	_       uint32  // unused // 未使用


// ChanDir represents a channel type's direction.
/**
 * ChanDir表示通道类型的方向。
 * 1: 发送通道
 * 2: 接收通道
 * 3: 双向通道
 **/
type ChanDir int

const (
	RecvDir ChanDir             = 1 << iota // <-chan // 发送通道
	SendDir                                 // chan<- // 接收通道
	BothDir = RecvDir | SendDir             // chan   // 双向通道
)

// arrayType represents a fixed array type.
/**
 * arrayType表示固定大小的数组类型。
 */
type arrayType struct 
	rtype // 通用数据类型
	elem  *rtype // array element type // 数组元素类型
	slice *rtype // slice type         // 切片类型
	len   uintptr                      // 数组类型的长度


// chanType represents a channel type.
/**
 * chanType表示通道类型。
 */
type chanType struct 
	rtype // 通用数据类型
	elem *rtype  // channel element type            // 通道元素类型
	dir  uintptr // channel direction (ChanDir)     // 通道方向(ChanDir)


// funcType represents a function type.
//
// A *rtype for each in and out parameter is stored in an array that
// directly follows the funcType (and possibly its uncommonType). So
// a function type with one method, one input, and one output is:
//
//	struct 
//		funcType
//		uncommonType
//		[2]*rtype    // [0] is in, [1] is out
//	
/**
 * funcType表示函数类型。
 *
 * 每个in和out参数的*rtype存储在一个数组中,该数组紧随funcType(可能还有其uncommonType)。
 * 因此,具有一个方法,一个输入和一个输出的函数类型为:
 *  struct 
 *      funcType
 *      uncommonType
 *      [2]*rtype    // [0]是输入参数, [1]输出结果
 *  
 */
type funcType struct 
	rtype // 通用数据类型
	inCount  uint16 // 输入参数的个数
	outCount uint16 // top bit is set if last input parameter is ... // 输出参数的个数,如果最后一个输入参数为...,则设置最高位


// imethod represents a method on an interface type
/**
 * imethod表示接口类型上的方法
 */
type imethod struct 
	name nameOff // name of method // 方法名
	typ  typeOff // .(*FuncType) underneath // Question: 这是什么


// interfaceType represents an interface type.
/**
 * interfaceType代表接口类型
 */
type interfaceType struct 
	rtype // 通用数据类型
	pkgPath name      // import path        // 导入路径
	methods []imethod // sorted by hash     // 接口方法,根据hash排序


// mapType represents a map type.
/**
 * mapType表示Map类型。
 */
type mapType struct 
	rtype // 通用数据类型
	key    *rtype // map key type                                   // map key的类型
	elem   *rtype // map element (value) type                       // map元素的类型
	bucket *rtype // internal bucket structure                      // hash桶结构
	// function for hashing keys (ptr to key, seed) -> hash         // hash函数
	hasher     func(unsafe.Pointer, uintptr) uintptr
	keysize    uint8  // size of key slot                           // key槽数
	valuesize  uint8  // size of value slot                         // value槽数
	bucketsize uint16 // size of bucket                             // 桶数
	flags      uint32                                               // Question: 用来做什么


// ptrType represents a pointer type.
/**
 * ptrType表示指针类型。
 */
type ptrType struct 
	rtype // 通用数据类型
	elem *rtype // pointer element (pointed at) type // 指针指向的元素类型


// sliceType represents a slice type.
/**
 * sliceType表示切片类型。
 */
type sliceType struct 
	rtype // 通用数据类型
	elem *rtype // slice element type // 切片元素类型


// Struct field
/**
 * 结构体字段类型
 */
type structField struct 
	name        name    // name is always non-empty                 // 名称始终为非空
	typ         *rtype  // type of field                            // 字段类型
	offsetEmbed uintptr // byte offset of field<<1 | isEmbedded     // 偏移量指针与嵌入类型共用字段

/**
 * 求偏移量
 * @return uintptr 偏移量指针
 * @date 2020-03-18 12:49:38
 **/
func (f *structField) offset() uintptr 
	return f.offsetEmbed >> 1


/**
 * 是否是嵌入类型
 * @return true: 是嵌入类型
 * @date 2020-03-18 12:50:47
 **/
func (f *structField) embedded() bool 
	return f.offsetEmbed&1 != 0


// structType represents a struct type.
/**
 * structType表示结构类型。
 **/
type structType struct 
	rtype // 通用数据类型
	pkgPath name // 包名
	fields  []structField // sorted by offset // 结构体字段,根据偏量排序


// name is an encoded type name with optional extra data.
//
// The first byte is a bit field containing:
//
//	1<<0 the name is exported
//	1<<1 tag data follows the name
//	1<<2 pkgPath nameOff follows the name and tag
//
// The next two bytes are the data length:
//
//	 l := uint16(data[1])<<8 | uint16(data[2])
//
// Bytes [3:3+l] are the string data.
//
// If tag data follows then bytes 3+l and 3+l+1 are the tag length,
// with the data following.
//
// If the import path follows, then 4 bytes at the end of
// the data form a nameOff. The import path is only set for concrete
// methods that are defined in a different package than their type.
//
// If a name starts with "*", then the exported bit represents
// whether the pointed to type is exported.
/**
 * name是带有可选附加数据的编码类型名称。
 *
 * 第一个字节是一个位字段,其中包含
 *  1 << 0 名称是可导出的
 *  1 << 1 标签数据跟随名称之后
 *  1 << 2 pkgPath nameOff跟随名称和标签数据之后
 *
 * 接下来的两个字节是数据长度:
 *  l := uint16(data[1])<<8 | uint16(data[2])
 * 字节[3:3+1]是字符串数据。
 * 数据结构示意思图,下划线表示一个位,+和|号表示分割符,...表示省略多个字节
 * +--------+--------+--------+--------...--------+--------+--------+--------...--------+--------+--------+--------+--------+
 * |     ???|    name len     |     name data     |     tag len     |      tag data     |          pkgPath nameOff          |
 * +--------+--------+--------+--------...--------+--------+--------+--------...--------+--------+--------+--------+--------+
 *
 * 如果名称后跟随标签数据,则字节3+1和3+1+1是标签长度,数据跟随在后面
 * 如果有导入路径,则数据末尾的4个字节形成nameOff
 * 仅为在与包类型不同的包中定义的具体方法设置导入路径。
 *
 * 如果名称以“*”开头,则导出的位表示是否导出了所指向的类型。
 */
type name struct 
	bytes *byte

/**
 * 添加字符串
 * @param 偏移量
 * @param 字符串,实际未使用到
 * @return 返回新的引用地址
 * @date 2020-03-19 08:28:49
 **/
func (n name) data(off int, whySafe string) *byte 
	return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))


/**
 * 是否是可导出类型
 * @return true: 是
 * @date 2020-03-19 08:31:13
 **/
func (n name) isExported() bool 
	return (*n.bytes)&(1<<0) != 0 // 最低位为0


/**
 * 名称长度
 * @return
 * @date 2020-03-19 08:33:18
 **/
func (n name) nameLen() int 
    // 0b表示前二进制前缀,a,b,c,d表示0或者1
    // bytes = [0baaaaaaaa, 0bbbbbbbbb, 0bcccccccc, 0bdddddddd]
    // A: uint16(*n.data(1, "name len field"))<<8 ==> 0bbbbbbbbb_?????????
    // B: uint16(*n.data(2, "name len field")) ==> 0b????????_cccccccc
    // A|B ==> 00bbbbbbbbb_cccccccc
	return int(uint16(*n.data(1, "name len field"))<<8 | uint16(*n.data(2, "name len field")))


/**
 * 获取标签的长度
 * @return
 * @date 2020-03-19 08:48:05
 **/
func (n name) tagLen() int 
    // 第一个字节的第二位是1说明有标签
	if *n.data(0, "name flag field")&(1<<1) == 0 
		return 0
	

	// 标签长度使用两个字节表示,第一个字节所在位置
	off := 3 + n.以上是关于go源码阅读——type.go的主要内容,如果未能解决你的问题,请参考以下文章

go源码阅读——value.go

go源码阅读——value.go

[Go] gocron源码阅读-空接口类型interface{}

Go语言学习之旅--接口

Go语言学习之旅--接口

Go语言学习之旅--接口