文件地址
基本結構圖
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.nameLen()
return int(uint16(*n.data(off, "name taglen field"))<<8 | uint16(*n.data(off+1, "name taglen field")))
}
/**
* 獲取名稱字符串
* @return 名稱字符串
* @date 2020-03-19 09:01:31
**/
func (n name) name() (s string) {
if n.bytes == nil {
return
}
b := (*[4]byte)(unsafe.Pointer(n.bytes)) // 創建一個地址
hdr := (*stringHeader)(unsafe.Pointer(&s)) // 創建stringHeader對象
hdr.Data = unsafe.Pointer(&b[3]) // 設置數據開始位置
hdr.Len = int(b[1])<<8 | int(b[2]) // 設置數據長度
return s
}
/**
* 獲取標籤字符串
* @return 標籤字符串
* @date 2020-03-19 09:39:21
**/
func (n name) tag() (s string) {
tl := n.tagLen() // 取標籤長度
if tl == 0 { // 說明沒有籤
return ""
}
nl := n.nameLen() // 取名稱長度
hdr := (*stringHeader)(unsafe.Pointer(&s)) // 創建stringHeader對象
hdr.Data = unsafe.Pointer(n.data(3+nl+2, "non-empty string")) // 標籤字符串地址
hdr.Len = tl // 設置長度
return s
}
/**
* 獲取包路徑信息
* @return 包路徑信息
* @date 2020-03-19 09:41:30
**/
func (n name) pkgPath() string {
// 第一個字節第三個位是0,說明沒有包路徑
if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 {
return ""
}
// 求包路徑的偏移量
off := 3 + n.nameLen()
if tl := n.tagLen(); tl > 0 {
off += 2 + tl
}
var nameOff int32 // 用於保存偏移量地址
// 請注意,該字段在內存中可能未對齊,因此在此我們不能使用直接的int32分配。
// Note that this field may not be aligned in memory,
// so we cannot use a direct int32 assignment here.
// 如果包路路徑存在,則n.data最後四個字節表示包路徑的偏移量地址,將最後四個字節取出,創建結構體,並且複製結構體
// Question: 原理是什麼?
copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off, "name offset field")))[:])
pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.bytes), nameOff))} // 創建name結構體
return pkgPathName.name() // 最終獲取包路徑信息
}
/**
* 創建name結構體,並未設置包路徑偏移量
* @param n 名稱字
* @param taq 標籤信息
* @param exported 是否可導出
* @return name結構體
* @date 2020-03-19 09:50:38
**/
func newName(n, tag string, exported bool) name {
// 長度不能大於65535
if len(n) > 1<<16-1 {
panic("reflect.nameFrom: name too long: " + n)
}
// 長度不能大於65535
if len(tag) > 1<<16-1 {
panic("reflect.nameFrom: tag too long: " + tag)
}
var bits byte // 標記字段
l := 1 + 2 + len(n) // l用於記錄數據長度
if exported { // 標記是否可導出
bits |= 1 << 0
}
if len(tag) > 0 { // 有標籤數據
l += 2 + len(tag)
bits |= 1 << 1 // 標記有標籤
}
b := make([]byte, l)
b[0] = bits // 設置位標記
b[1] = uint8(len(n) >> 8) // 設置名稱長度
b[2] = uint8(len(n))
copy(b[3:], n) // 拷貝名稱數據
if len(tag) > 0 { // 有標籤數據
tb := b[3+len(n):]
tb[0] = uint8(len(tag) >> 8) // 設置標籤長度
tb[1] = uint8(len(tag))
copy(tb[2:], tag) // 拷貝標籤數據
}
return name{bytes: &b[0]}
}
/**
* The compiler knows the exact layout of all the data structures above.
* The compiler does not know about the data structures and methods below.
* 編譯器知道上面所有數據結構的確切佈局。
* 編譯器不瞭解以下數據結構和方法。
*/
// Method represents a single method.
/**
* Method表示一個方法類型
*/
type Method struct {
// Name is the method name.
// PkgPath is the package path that qualifies a lower case (unexported)
// method name. It is empty for upper case (exported) method names.
// The combination of PkgPath and Name uniquely identifies a method
// in a method set.
// See https://golang.org/ref/spec#Uniqueness_of_identifiers
/**
* Name是方法名稱。
* PkgPath是包含小寫(未導出)方法名稱的程序包路徑。大寫(導出)的方法名稱PkgPath爲空。
* PkgPath和Name的組合唯一標識方法集中的方法。
* 參見https://golang.org/ref/spec#Uniqueness_of_identifiers
*/
Name string
PkgPath string
Type Type // method type // 方法類型
Func Value // func with receiver as first argument // 以接收者爲第一個參數的func
Index int // index for Type.Method // Type.Method的索引
}
const (
kindDirectIface = 1 << 5 // 0b00100000
kindGCProg = 1 << 6 // Type.gc points to GC program // Type.gc指向GC程序 // 0b01000000
kindMask = (1 << 5) - 1 // 0b00011111
)
// String returns the name of k.
/**
* 字符串返回k的名稱。
@return string k的名稱字符串
*/
func (k Kind) String() string {
if int(k) < len(kindNames) {
return kindNames[k]
}
return "kind" + strconv.Itoa(int(k))
}
/**
* 類型和名稱映射
*/
var kindNames = []string{
Invalid: "invalid",
Bool: "bool",
Int: "int",
Int8: "int8",
Int16: "int16",
Int32: "int32",
Int64: "int64",
Uint: "uint",
Uint8: "uint8",
Uint16: "uint16",
Uint32: "uint32",
Uint64: "uint64",
Uintptr: "uintptr",
Float32: "float32",
Float64: "float64",
Complex64: "complex64",
Complex128: "complex128",
Array: "array",
Chan: "chan",
Func: "func",
Interface: "interface",
Map: "map",
Ptr: "ptr",
Slice: "slice",
String: "string",
Struct: "struct",
UnsafePointer: "unsafe.Pointer",
}
/**
* 獲取類型上定義的所有方法,包括未導出的方法
* @return 類型上定義的所有方法
* @date 2020-03-20 08:37:57
**/
func (t *uncommonType) methods() []method {
if t.mcount == 0 {
return nil
}
// 一個長度是65536個的數組,從中取指定位置的值
// 切片從0到第t.mcount-1位,長度爲t.mcount,最大擴充項cap設置爲t.mcount
return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount]
}
/**
* 獲取類型上定義的所有導出的方法
* @return 類型上定義的所有導出的方法
* @date 2020-03-20 08:37:57
**/
func (t *uncommonType) exportedMethods() []method {
if t.xcount == 0 {
return nil
}
return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount]
}
// resolveNameOff resolves a name offset from a base pointer.
// The (*rtype).nameOff method is a convenience wrapper for this function.
// Implemented in the runtime package.
/**
* resolveNameOff解析與名稱基本指針的偏移量。 (*rtype).nameOff方法是此功能的便捷包裝。在runtime包中實現。
* @param ptrInModule 模塊中的指針對象
* @param off 偏移量
* @return 計算後的打針對象
* @date 2020-03-20 08:46:29
**/
func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
// resolveTypeOff resolves an *rtype offset from a base type.
// The (*rtype).typeOff method is a convenience wrapper for this function.
// Implemented in the runtime package.
/**
* resolveTypeOff解析*rtype與基本類型的偏移量。(*rtype).typeOff方法是此函數的便捷包裝。在runtime包中實現。
* @param 類型的指針
* @param 偏移量
* @return 計算後的類型指針
* @date 2020-03-20 08:49:12
**/
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
// resolveTextOff resolves a function pointer offset from a base type.
// The (*rtype).textOff method is a convenience wrapper for this function.
// Implemented in the runtime package.
/**
* resolveTextOff解析函數指針與基本類型的偏移量。(*rtype).textOff方法是此函數的便捷包裝。在runtime包中實現。
* @param 類型的指針
* @param 偏移量
* @return 計算後的類型指針
* @date 2020-03-20 08:49:12
**/
func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
// addReflectOff adds a pointer to the reflection lookup map in the runtime.
// It returns a new ID that can be used as a typeOff or textOff, and will
// be resolved correctly. Implemented in the runtime package.
/**
* addReflectOff在運行時中將一個指針添加到反射查找map。返回一個新的ID,該ID可以用作typeOff或textOff,並且可以正確解析。在運行時包中實現。
* @param 指針
* @param 偏移量
* @return 新的ID
* @date 2020-03-20 08:49:12
**/
func addReflectOff(ptr unsafe.Pointer) int32
// resolveReflectType adds a name to the reflection lookup map in the runtime.
// It returns a new nameOff that can be used to refer to the pointer.
/**
* resolveReflectType在運行時爲反射查找map添加名稱。它返回一個新的nameOff,可以用來引用該指針。
* @param n 名稱
* @return 新的nameOff
* @date 2020-03-20 08:54:31
**/
func resolveReflectName(n name) nameOff {
return nameOff(addReflectOff(unsafe.Pointer(n.bytes)))
}
// resolveReflectType adds a *rtype to the reflection lookup map in the runtime.
// It returns a new typeOff that can be used to refer to the pointer.
/**
* resolveReflectType在運行時將*rtype添加到反射查找map中。它返回一個新的typeOff,可以用來引用該指針。
* @param t 類型
* @return 新的typeOff
* @date 2020-03-20 08:55:32
**/
func resolveReflectType(t *rtype) typeOff {
return typeOff(addReflectOff(unsafe.Pointer(t)))
}
// resolveReflectText adds a function pointer to the reflection lookup map in
// the runtime. It returns a new textOff that can be used to refer to the
// pointer.
/**
* resolveReflectText將函數指針添加到反射查找map中,運行時。它返回一個新的textOff,可以用來引用該指針。
* @param ptr 指針
* @return 新的textOff
* @return
* @date 2020-03-20 08:57:01
**/
func resolveReflectText(ptr unsafe.Pointer) textOff {
return textOff(addReflectOff(ptr))
}
type nameOff int32 // offset to a name // 到一個name的偏移量
type typeOff int32 // offset to an *rtype // 到*rtype的偏移量
type textOff int32 // offset from top of text section // 與文字部分頂部的偏移量
/**
* 根據nameOff創建name實體
* @param off 到一個name的偏移量
* @return name對象
* @date 2020-03-20 08:59:24
**/
func (t *rtype) nameOff(off nameOff) name {
return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
}
/**
* 根據typeOff創建rtype結構體指針
* @param 到*rtype的偏移量
* @return rtype的指針
* @date 2020-03-20 09:00:10
**/
func (t *rtype) typeOff(off typeOff) *rtype {
return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
}
/**
* 根據textOff指針結構體實例
* @param 與文字部分頂部的偏移量
* @return 指針結構體實例
* @date 2020-03-20 09:02:56
**/
func (t *rtype) textOff(off textOff) unsafe.Pointer {
return resolveTextOff(unsafe.Pointer(t), int32(off))
}
/**
* 求rtype的uncommonType,返回是uncommonType指針
* @return uncommonType指針
* @date 2020-03-20 09:33:28
**/
func (t *rtype) uncommon() *uncommonType {
if t.tflag&tflagUncommon == 0 { // uncommonType不存在
return nil
}
// 根據不同的類型,創建對應的xxxTypeUncommon,返回其uncommonType類型指針
switch t.Kind() {
case Struct:
return &(*structTypeUncommon)(unsafe.Pointer(t)).u
case Ptr:
type u struct {
ptrType
u uncommonType
}
return &(*u)(unsafe.Pointer(t)).u
case Func:
type u struct {
funcType
u uncommonType
}
return &(*u)(unsafe.Pointer(t)).u
case Slice:
type u struct {
sliceType
u uncommonType
}
return &(*u)(unsafe.Pointer(t)).u
case Array:
type u struct {
arrayType
u uncommonType
}
return &(*u)(unsafe.Pointer(t)).u
case Chan:
type u struct {
chanType
u uncommonType
}
return &(*u)(unsafe.Pointer(t)).u
case Map:
type u struct {
mapType
u uncommonType
}
return &(*u)(unsafe.Pointer(t)).u
case Interface:
type u struct {
interfaceType
u uncommonType
}
return &(*u)(unsafe.Pointer(t)).u
default:
type u struct {
rtype
u uncommonType
}
return &(*u)(unsafe.Pointer(t)).u
}
}
/**
* 獲取rtype類型的字符表示
* @return type類型的字符表示
* @date 2020-03-20 09:39:55
**/
func (t *rtype) String() string {
s := t.nameOff(t.str).name()
if t.tflag&tflagExtraStar != 0 { // 有額外的*號前綴
return s[1:]
}
return s
}
/**
* 獲取rtype類型的size屬性值
* @return size屬性值
* @date 2020-03-20 09:41:46
**/
func (t *rtype) Size() uintptr { return t.size }
/**
* rtype所代表的數據值,在內存中表示需要的位數,只能求數值類型的,非數值類型會引起panic
* @param
* @param
* @return
* @return
* @date 2020-03-20 09:43:37
**/
func (t *rtype) Bits() int {
if t == nil { // 類型不能爲空
panic("reflect: Bits of nil Type")
}
// 不能是非數值類型
k := t.Kind()
if k < Int || k > Complex128 {
panic("reflect: Bits of non-arithmetic Type " + t.String())
}
// 求位數
return int(t.size) * 8
}
func (t *rtype) Align() int { return int(t.align) }
func (t *rtype) FieldAlign() int { return int(t.fieldAlign) }
func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
func (t *rtype) pointers() bool { return t.ptrdata != 0 }
func (t *rtype) common() *rtype { return t }
/**
* 求rtype的代表的值的導出方法,有uncommonType纔可能有導出類型
* @return 導出方法
* @date 2020-03-20 09:50:20
**/
func (t *rtype) exportedMethods() []method {
ut := t.uncommon()
if ut == nil {
return nil
}
return ut.exportedMethods()
}
/**
* 求rtype的代表的值的導出方法數
* @return 導出方法數
* @date 2020-03-20 09:58:24
**/
func (t *rtype) NumMethod() int {
if t.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(t))
return tt.NumMethod()
}
return len(t.exportedMethods())
}
/**
* 求導出方法中的第i個方法
* @param i 第i個方法,0開始計數
* @return 方法結構體實例
* @date 2020-03-20 10:14:22
**/
func (t *rtype) Method(i int) (m Method) {
// 接口類型
if t.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(t))
return tt.Method(i)
}
// 非接口類型
methods := t.exportedMethods()
if i < 0 || i >= len(methods) {
panic("reflect: Method index out of range")
}
p := methods[i]
pname := t.nameOff(p.name) // 根據nameOff創建name實例
m.Name = pname.name()
fl := flag(Func)
mtyp := t.typeOff(p.mtyp) // 根據typeOff創建rtype結構體,並反回指針
ft := (*funcType)(unsafe.Pointer(mtyp)) // 獲取方法類型
in := make([]Type, 0, 1+len(ft.in()))
in = append(in, t) // 方法的第一個入參表示方法的接收者
for _, arg := range ft.in() { // 添加入參
in = append(in, arg)
}
out := make([]Type, 0, len(ft.out()))
for _, ret := range ft.out() { // 添加出參
out = append(out, ret)
}
// FuncOf返回具有給定參數和結果類型的函數類型。
mt := FuncOf(in, out, ft.IsVariadic())
m.Type = mt // 設置方法類型
tfn := t.textOff(p.tfn) // 求函數的textOff
fn := unsafe.Pointer(&tfn)
m.Func = Value{mt.(*rtype), fn, fl} // 設置方法值,可使用此值調用方法
m.Index = i // 設置是第幾個方法
return m
}
/**
* 根據名稱查找導出的方法
* @param name 方法名
* @return m 找到的方法
* @return ok true: 找到方法
* @date 2020-03-21 11:21:50
**/
func (t *rtype) MethodByName(name string) (m Method, ok bool) {
// 接口類型
if t.Kind() == Interface {
tt := (*interfaceType)(unsafe.Pointer(t))
return tt.MethodByName(name)
}
// 非接口類型
ut := t.uncommon()
if ut == nil {
return Method{}, false
}
// TODO(mdempsky): Binary search.
// 根據名稱找到對應的方法索引,再根據索引找到對應的方法
for i, p := range ut.exportedMethods() {
if t.nameOff(p.name).name() == name {
return t.Method(i), true
}
}
return Method{}, false
}
/**
* 獲取包路徑信息,沒有返回""
* @return 包路徑信息,沒有返回""
* @date 2020-03-21 11:25:34
**/
func (t *rtype) PkgPath() string {
if t.tflag&tflagNamed == 0 {
return ""
}
ut := t.uncommon()
if ut == nil {
return ""
}
return t.nameOff(ut.pkgPath).name()
}
/**
* 類型是否有名稱
* @return 類型是否有名稱。true: 是
* @date 2020-03-21 11:26:48
**/
func (t *rtype) hasName() bool {
return t.tflag&tflagNamed != 0
}
/**
* 獲取類型的名稱
* @return 類型的名稱
* @date 2020-03-21 11:28:20
**/
func (t *rtype) Name() string {
if !t.hasName() {
return ""
}
s := t.String()
i := len(s) - 1
for i >= 0 && s[i] != '.' { // 找最後的一個.號的位置
i--
}
return s[i+1:]
}
/**
* 獲取類型的通道類型,如果不是通道類型,引起panic
* @return 通道類型
* @date 2020-03-21 11:29:24
**/
func (t *rtype) ChanDir() ChanDir {
if t.Kind() != Chan {
panic("reflect: ChanDir of non-chan type " + t.String())
}
tt := (*chanType)(unsafe.Pointer(t))
return ChanDir(tt.dir)
}
/**
* 是否有可變參數,如要不是Func類型,引起panic
* @return true: 有可變參數類型
* @date 2020-03-21 11:31:13
**/
func (t *rtype) IsVariadic() bool {
if t.Kind() != Func {
panic("reflect: IsVariadic of non-func type " + t.String())
}
tt := (*funcType)(unsafe.Pointer(t))
return tt.outCount&(1<<15) != 0 // outCount最高位爲1說明有可變參數
}
/**
* 獲取元素類型,此方法只對Array, Chan, Map, Ptr, Slice類型有效,其他類型返回Panic
* @return 元素類型
* @date 2020-03-21 11:33:37
**/
func (t *rtype) Elem() Type {
switch t.Kind() {
case Array:
tt := (*arrayType)(unsafe.Pointer(t))
return toType(tt.elem)
case Chan:
tt := (*chanType)(unsafe.Pointer(t))
return toType(tt.elem)
case Map:
tt := (*mapType)(unsafe.Pointer(t))
return toType(tt.elem)
case Ptr:
tt := (*ptrType)(unsafe.Pointer(t))
return toType(tt.elem)
case Slice:
tt := (*sliceType)(unsafe.Pointer(t))
return toType(tt.elem)
}
panic("reflect: Elem of invalid type " + t.String())
}
/**
* 獲取第i個屬性,非結構體類型會引起panic
* @param 第i個屬性
* @return 結構體屬性實例
* @date 2020-03-21 11:35:14
**/
func (t *rtype) Field(i int) StructField {
if t.Kind() != Struct {
panic("reflect: Field of non-struct type " + t.String())
}
tt := (*structType)(unsafe.Pointer(t))
return tt.Field(i)
}
/**
* 獲取屬性,參數表示層次關係,非結構體類型會引起panic
* @param 屬性位置切片
* @return 結構體屬性實例
* @date 2020-03-21 11:35:14
**/
func (t *rtype) FieldByIndex(index []int) StructField {
if t.Kind() != Struct {
panic("reflect: FieldByIndex of non-struct type " + t.String())
}
tt := (*structType)(unsafe.Pointer(t))
return tt.FieldByIndex(index)
}
/**
* 根據名稱找到對應的屬性
* @param 屬性名
* @return 結構體屬性實例
* @return true: 找到
* @date 2020-03-21 11:39:00
**/
func (t *rtype) FieldByName(name string) (StructField, bool) {
if t.Kind() != Struct {
panic("reflect: FieldByName of non-struct type " + t.String())
}
tt := (*structType)(unsafe.Pointer(t))
return tt.FieldByName(name)
}
/**
* 根據匹配函數找到對應的屬性
* @param 匹配函數
* @return 結構體屬性實例
* @return true: 找到
* @date 2020-03-21 11:39:00
**/
func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
if t.Kind() != Struct {
panic("reflect: FieldByNameFunc of non-struct type " + t.String())
}
tt := (*structType)(unsafe.Pointer(t))
return tt.FieldByNameFunc(match)
}
/**
* 方法的第i個入參的類型
* @param 第i個入參
* @return 第i個入參的類型
* @date 2020-03-21 11:43:56
**/
func (t *rtype) In(i int) Type {
if t.Kind() != Func {
panic("reflect: In of non-func type " + t.String())
}
tt := (*funcType)(unsafe.Pointer(t))
return toType(tt.in()[i])
}
/**
* Map的key類型
* @return Map的key類型
* @date 2020-03-21 11:44:36
**/
func (t *rtype) Key() Type {
if t.Kind() != Map {
panic("reflect: Key of non-map type " + t.String())
}
tt := (*mapType)(unsafe.Pointer(t))
return toType(tt.key)
}
/**
* 獲取數組長度
* @return 數組長度
* @date 2020-03-21 11:46:22
**/
func (t *rtype) Len() int {
if t.Kind() != Array {
panic("reflect: Len of non-array type " + t.String())
}
tt := (*arrayType)(unsafe.Pointer(t))
return int(tt.len)
}
/**
* 結構的字段數目
* @return 結構的字段數目
* @date 2020-03-21 11:47:34
**/
func (t *rtype) NumField() int {
if t.Kind() != Struct {
panic("reflect: NumField of non-struct type " + t.String())
}
tt := (*structType)(unsafe.Pointer(t))
return len(tt.fields)
}
/**
* 方法的入參個數
* @return
* @date 2020-03-21 11:48:04
**/
func (t *rtype) NumIn() int {
if t.Kind() != Func {
panic("reflect: NumIn of non-func type " + t.String())
}
tt := (*funcType)(unsafe.Pointer(t))
return int(tt.inCount)
}
/**
* 方法的出參個數
* @return 方法的出參個數
* @date 2020-03-21 11:48:21
**/
func (t *rtype) NumOut() int {
if t.Kind() != Func {
panic("reflect: NumOut of non-func type " + t.String())
}
tt := (*funcType)(unsafe.Pointer(t))
return len(tt.out())
}
/**
* 方法的第i個出參
* @param 第i個出參
* @return 第i個出參類型
* @date 2020-03-21 11:48:43
**/
func (t *rtype) Out(i int) Type {
if t.Kind() != Func {
panic("reflect: Out of non-func type " + t.String())
}
tt := (*funcType)(unsafe.Pointer(t))
return toType(tt.out()[i])
}
/**
* 所有的入參
* @return 所有的入參
* @date 2020-03-21 11:49:56
**/
func (t *funcType) in() []*rtype {
uadd := unsafe.Sizeof(*t)
if t.tflag&tflagUncommon != 0 {
uadd += unsafe.Sizeof(uncommonType{})
}
// 這裏可以提到前面
if t.inCount == 0 {
return nil
}
return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.inCount:t.inCount]
}
/**
* 所有的出參
* @return
* @date 2020-03-21 11:50:19
**/
func (t *funcType) out() []*rtype {
uadd := unsafe.Sizeof(*t)
if t.tflag&tflagUncommon != 0 {
uadd += unsafe.Sizeof(uncommonType{})
}
// 判斷可以提前
outCount := t.outCount & (1<<15 - 1)
if outCount == 0 {
return nil
}
return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.inCount : t.inCount+outCount : t.inCount+outCount]
}
// add returns p+x.
//
// The whySafe string is ignored, so that the function still inlines
// as efficiently as p+x, but all call sites should use the string to
// record why the addition is safe, which is to say why the addition
// does not cause x to advance to the very end of p's allocation
// and therefore point incorrectly at the next block in memory.
/**
* add返回p + x。
*
* whySafe字符串將被忽略,因此該函數仍然可以像p+x一樣有效地內聯,
* 但是所有調用站點都應使用該字符串來記錄爲什麼加法是安全的,
* 也就是說加法爲何不會導致x提前到p分配的末尾,因此而錯誤地指向了內存中的下一個塊。
* @param p 指針類型
* @param x 偏移量
* @param whySafe 提示字符串
* @return 新的指針類型
* @return
* @date 2020-03-21 14:40:58
**/
func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
return unsafe.Pointer(uintptr(p) + x)
}
/**
* 通道方向字符串描述
* @return 通道方向字符串描述
* @date 2020-03-21 14:42:43
**/
func (d ChanDir) String() string {
switch d {
case SendDir:
return "chan<-"
case RecvDir:
return "<-chan"
case BothDir:
return "chan"
}
return "ChanDir" + strconv.Itoa(int(d))
}
// Method returns the i'th method in the type's method set.
/**
* 方法返回類型的方法集中的第i個方法。
* @return 方法集中的第i個方法
* @date 2020-03-21 14:43:31
**/
func (t *interfaceType) Method(i int) (m Method) {
if i < 0 || i >= len(t.methods) { //
return
}
p := &t.methods[i]
pname := t.nameOff(p.name)
m.Name = pname.name() // 設置方法名
if !pname.isExported() { // 如果方法是可導出的,則設置方法名
m.PkgPath = pname.pkgPath()
if m.PkgPath == "" { // pname上的名稱可能爲空,則取接口類型上的包名
m.PkgPath = t.pkgPath.name()
}
}
m.Type = toType(t.typeOff(p.typ)) // 設置方法的type類類型
m.Index = i // 設置是接口的第i個方法
return
}
// NumMethod returns the number of interface methods in the type's method set.
/**
* NumMethod返回類型的方法集中的接口方法的數量。
* @return 方法集中的接口方法的數量
* @date 2020-03-21 14:52:34
**/
func (t *interfaceType) NumMethod() int { return len(t.methods) }
// MethodByName method with the given name in the type's method set.
func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
if t == nil {
return
}
var p *imethod
for i := range t.methods {
p = &t.methods[i]
if t.nameOff(p.name).name() == name {
return t.Method(i), true
}
}
return
}
// A StructField describes a single field in a struct.
/**
* StructField描述結構中的單個字段。
*/
type StructField struct {
// Name is the field name.
// 字段名稱
Name string
// PkgPath is the package path that qualifies a lower case (unexported)
// field name. It is empty for upper case (exported) field names.
// See https://golang.org/ref/spec#Uniqueness_of_identifiers
/**
* PkgPath是限定小寫(未導出)字段名稱的程序包路徑。大寫(導出)字段名稱爲空。
* 參見https://golang.org/ref/spec#Uniqueness_of_identifiers
*/
PkgPath string
/**
* 字段類型
*/
Type Type // field type
/**
* 標籤信息
*/
Tag StructTag // field tag string
/**
* 結構體中的偏移量(以字節爲單位)
*/
Offset uintptr // offset within struct, in bytes
/**
* Type.FieldByIndex的索引序列
*/
Index []int // index sequence for Type.FieldByIndex
/**
* 是否是內嵌字段
*/
Anonymous bool // is an embedded field
}
// A StructTag is the tag string in a struct field.
//
// By convention, tag strings are a concatenation of
// optionally space-separated key:"value" pairs.
// Each key is a non-empty string consisting of non-control
// characters other than space (U+0020 ' '), quote (U+0022 '"'),
// and colon (U+003A ':'). Each value is quoted using U+0022 '"'
// characters and Go string literal syntax.
/**
* StructTag是struct字段中的標籤字符串。
*
* 按照慣例,標籤字符串是由空格分隔的key:"value"對組成的串聯。
* 每個key都是非空字符串,由非控制字符組成,除了空格(U+0020 ' '),引號(U+0022 '"')
* 和冒號(U+003A ':')。每個值使用U+0022 '"字符和Go字符串文字語法引用。
*/
type StructTag string
// Get returns the value associated with key in the tag string.
// If there is no such key in the tag, Get returns the empty string.
// If the tag does not have the conventional format, the value
// returned by Get is unspecified. To determine whether a tag is
// explicitly set to the empty string, use Lookup.
/**
* Get返回與標籤字符串中的key關聯的值。
* 如果標籤中沒有這樣的鍵,則Get返回空字符串。
* 如果標記不具有常規格式,則未指定Get返回的值。
* 若要確定是否將標記明確設置爲空字符串,請使用Lookup。
*/
func (tag StructTag) Get(key string) string {
v, _ := tag.Lookup(key)
return v
}
// Lookup returns the value associated with key in the tag string.
// If the key is present in the tag the value (which may be empty)
// is returned. Otherwise the returned value will be the empty string.
// The ok return value reports whether the value was explicitly set in
// the tag string. If the tag does not have the conventional format,
// the value returned by Lookup is unspecified.
/**
* 標籤格式 : `a:"b",c:"d",e:"f"`
* 查找返回與標籤字符串中的鍵關聯的值。
* 如果關鍵字存在於標籤中,則返回值(可能爲空)。否則,返回值將爲空字符串。
* ok返回值報告該值是否在標記字符串中顯式設置。如果標記不具有常規格式,則未指定Lookup返回的值。
*/
func (tag StructTag) Lookup(key string) (value string, ok bool) {
// When modifying this code, also update the validateStructTag code
// in cmd/vet/structtag.go.
/**
* 修改此代碼時,還請更新cmd/vet/structtag.go中的validateStructTag代碼。
*/
for tag != "" {
// Skip leading space.
// 忽略前導空格
i := 0
for i < len(tag) && tag[i] == ' ' {
i++
}
tag = tag[i:]
if tag == "" {
break
}
// Scan to colon. A space, a quote or a control character is a syntax error.
// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
// as it is simpler to inspect the tag's bytes than the tag's runes.
// 掃描到冒號。空格,引號或控制字符是語法錯誤。
// 嚴格來說,控制字符包括範圍[0x7f,0x9f],而不僅僅是
// [0x00,0x1f],但實際上,我們忽略了多字節控制字符
// 因爲檢查標記的字節比標記的符文更簡單。
i = 0
for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
i++
}
// 沒找到或者格式不合法的情況
if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
break
}
name := string(tag[:i]) // 標籤名
tag = tag[i+1:] // 標籤值開始的切片
// Scan quoted string to find value.
// Scan quoted string to find value.
i = 1
for i < len(tag) && tag[i] != '"' { // 在不越界的情況下,直到第一個非轉義"爲止
if tag[i] == '\\' {
i++
}
i++
}
if i >= len(tag) {
break
}
qvalue := string(tag[:i+1]) // 雙引號引起的字符串
tag = tag[i+1:]
if key == name { // 名稱相等的情況下
value, err := strconv.Unquote(qvalue) // 去掉引號後的字符串
if err != nil {
break
}
return value, true
}
}
return "", false
}
// Field returns the i'th struct field.
/**
* Field返回第i個struct字段。
*/
func (t *structType) Field(i int) (f StructField) {
if i < 0 || i >= len(t.fields) { // 不存在第i個字段
panic("reflect: Field index out of bounds")
}
p := &t.fields[i]
f.Type = toType(p.typ) // 設置字段類型
f.Name = p.name.name() // 設置字段名
f.Anonymous = p.embedded() // 設置是否內嵌字段
if !p.name.isExported() { // 非導出字段要設置包名
f.PkgPath = t.pkgPath.name()
}
if tag := p.name.tag(); tag != "" { // 存在標籤就設置標籤
f.Tag = StructTag(tag)
}
f.Offset = p.offset() // 設置偏移量
// NOTE(rsc): This is the only allocation in the interface
// presented by a reflect.Type. It would be nice to avoid,
// at least in the common cases, but we need to make sure
// that misbehaving clients of reflect cannot affect other
// uses of reflect. One possibility is CL 5371098, but we
// postponed that ugliness until there is a demonstrated
// need for the performance. This is issue 2320.
// NOTE(rsc):這是reflect.Type在接口中提供的唯一分配。
// 至少在通常情況下,最好避免這樣做,但是我們需要確保行爲不當的反射
// 客戶不會影響反射的其他用途。 一種可能是CL 5371098,但我們推遲了
// 這種醜陋,直到表現出對性能的需求爲止。 issue 2320。
f.Index = []int{i} // 設置索引
return
}
// TODO(gri): Should there be an error/bool indicator if the index
// is wrong for FieldByIndex?
// TODO(gri): 如果FieldByIndex的索引錯誤,是否應該有一個錯誤/布爾指示器?
// FieldByIndex returns the nested field corresponding to index.
/**
* FieldByIndex返回與索引對應的嵌套字段。
* @param index 索引數組
* @return 與索引對應的嵌套字段
*/
func (t *structType) FieldByIndex(index []int) (f StructField) {
f.Type = toType(&t.rtype)
for i, x := range index { // 遍歷索引
if i > 0 {
ft := f.Type
if ft.Kind() == Ptr && ft.Elem().Kind() == Struct { // 結構體指針類型特殊處理
ft = ft.Elem()
}
f.Type = ft
}
f = f.Type.Field(x)
}
return
}
// A fieldScan represents an item on the fieldByNameFunc scan work list.
/**
* fieldScan代表fieldByNameFunc掃描工作列表上的條目。
*/
type fieldScan struct {
typ *structType // 結構體類型
index []int // 索引數組
}
// FieldByNameFunc returns the struct field with a name that satisfies the
// match function and a boolean to indicate if the field was found.
/**
* FieldByNameFunc返回具有滿足match函數名稱的struct字段和一個布爾值,以指示是否找到了該字段。
* @param match 匹配函數
* @return result 結構體字段
* @return 是否找到,true: 是
* @date 2020-03-21 16:22:31
**/
func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
// This uses the same condition that the Go language does: there must be a unique instance
// of the match at a given depth level. If there are multiple instances of a match at the
// same depth, they annihilate each other and inhibit any possible match at a lower level.
// The algorithm is breadth first search, one depth level at a time.
/**
* 這使用了與Go語言相同的條件:在給定的深度級別,必須有唯一的匹配實例。
* 如果在同一深度有多個匹配的實例,它們將相消滅制並在較低級別禁止任何可能的匹配。
* 該算法是廣度優先搜索,一次一個深度級別。
*/
// The current and next slices are work queues:
// current lists the fields to visit on this depth level,
// and next lists the fields on the next lower level.
/**
* 當前和下一個切片是工作隊列:
* 當前列出了在此深度級別上要訪問的字段,下一個列出了下一個較低級別的字段。
*/
current := []fieldScan{}
next := []fieldScan{{typ: t}}
// nextCount records the number of times an embedded type has been
// encountered and considered for queueing in the 'next' slice.
// We only queue the first one, but we increment the count on each.
// If a struct type T can be reached more than once at a given depth level,
// then it annihilates itself and need not be considered at all when we
// process that next depth level.
/**
* nextCount記錄遇到嵌入式類型並考慮在“下一個”切片中進行排隊的次數。
* 我們只將第一個入隊列,但是我們增加每個的計數。 如果在給定的深度級別可以多次到達結構類型T,
* 那麼它將消滅自身,並且在我們處理下一個深度級別時完全不需要考慮。
*/
var nextCount map[*structType]int
// visited records the structs that have been considered already.
// Embedded pointer fields can create cycles in the graph of
// reachable embedded types; visited avoids following those cycles.
// It also avoids duplicated effort: if we didn't find the field in an
// embedded type T at level 2, we won't find it in one at level 4 either.
/**
* 訪問記錄了已經考慮過的結構。
* 嵌入式指針字段可以在可到達的嵌入式類型圖中創建循環; 來訪者避免陷入這些循環。
* 這也避免了重複的工作:如果我們在第2級沒有找到嵌入類型T中的字段,
* 那麼在第4級也不會在一個類型中找到該字段。
*/
visited := map[*structType]bool{}
for len(next) > 0 {
current, next = next, current[:0] // current變成現在要處理的層,next再次記錄下一層
count := nextCount
nextCount = nil
// Process all the fields at this depth, now listed in 'current'.
// The loop queues embedded fields found in 'next', for processing during the next
// iteration. The multiplicity of the 'current' field counts is recorded
// in 'count'; the multiplicity of the 'next' field counts is recorded in 'nextCount'.
/**
* 處理此深度的所有字段,現在列在“current”中。
* 循環將'next'中找到的嵌入字段入隊,以便在下一次迭代中進行處理。
* “current”字段計數的多重性記錄在“count”中; “next”字段計數的多重性記錄在“nextCount”中。
*/
for _, scan := range current {
t := scan.typ
if visited[t] {
// We've looked through this type before, at a higher level.
// That higher level would shadow the lower level we're now at,
// so this one can't be useful to us. Ignore it.
/**
* 之前,我們已經在更高層次上處理了這種類型。
* 較高的級別將掩蓋我們現在所處的較低級別,因此這一級別對我們沒有用。忽略它。
*/
continue
}
visited[t] = true
for i := range t.fields {
f := &t.fields[i]
// Find name and (for embedded field) type for field f.
// 查找字段f的名稱和(對於嵌入式字段)類型。
fname := f.name.name()
var ntyp *rtype
if f.embedded() {
// Embedded field of type T or *T.
// 類型T或* T的嵌入式字段。
ntyp = f.typ
if ntyp.Kind() == Ptr {
ntyp = ntyp.Elem().common()
}
}
// Does it match?
// 是否匹配
if match(fname) {
// Potential match
// 潛在匹配
if count[t] > 1 || ok {
// Name appeared multiple times at this level: annihilate.
// 在此級別上,名字多次出現:殲滅。
return StructField{}, false
}
result = t.Field(i) // 取屬性,並且設置索引列表
result.Index = nil
result.Index = append(result.Index, scan.index...)
result.Index = append(result.Index, i)
ok = true
continue
}
// Queue embedded struct fields for processing with next level,
// but only if we haven't seen a match yet at this level and only
// if the embedded types haven't already been queued.
/**
* 將嵌入的struct字段入隊列,以進行下一級別的處理,但前提是我們尚未在此級別看到匹配項,
* 並且僅當尚未對嵌入的類型進行入隊列時。
*/
if ok || ntyp == nil || ntyp.Kind() != Struct {
continue
}
styp := (*structType)(unsafe.Pointer(ntyp))
if nextCount[styp] > 0 {
// 已經現匹配過兩次了,那就不需要再處理了
nextCount[styp] = 2 // exact multiple doesn't matter
continue
}
if nextCount == nil {
nextCount = map[*structType]int{}
}
nextCount[styp] = 1 // 本層已經見到過,下一層也要標記起來
if count[t] > 1 { // 本層見過多次,下層也要標記見過多次
nextCount[styp] = 2 // exact multiple doesn't matter // 2就表示多次
}
var index []int
index = append(index, scan.index...)
index = append(index, i)
next = append(next, fieldScan{styp, index})
}
}
if ok {
break
}
}
return
}
// FieldByName returns the struct field with the given name
// and a boolean to indicate if the field was found.
/**
* FieldByName返回具有給定名稱的struct字段和一個布爾值,以指示是否找到了該字段。
*/
func (t *structType) FieldByName(name string) (f StructField, present bool) {
// Quick check for top-level name, or struct without embedded fields.
// 快速檢查頂級名稱或沒有嵌入字段的結構。
hasEmbeds := false
if name != "" {
for i := range t.fields {
tf := &t.fields[i]
if tf.name.name() == name {
return t.Field(i), true
}
if tf.embedded() {
hasEmbeds = true
}
}
}
if !hasEmbeds {
return
}
// 有嵌入字段在這裏進行處理
return t.FieldByNameFunc(func(s string) bool { return s == name })
}
// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
/**
* TypeOf返回表示i的動態類型的反射類型。如果i是nil接口值,則TypeOf返回nil。
**/
func TypeOf(i interface{}) Type {
eface := *(*emptyInterface)(unsafe.Pointer(&i))
return toType(eface.typ)
}
// ptrMap is the cache for PtrTo.
/**
* ptrMap是PtrTo的緩存。
*/
var ptrMap sync.Map // map[*rtype]*ptrType
// PtrTo returns the pointer type with element t.
// For example, if t represents type Foo, PtrTo(t) represents *Foo.
/**
* PtrTo返回帶有元素t的指針類型。例如,如果t表示類型Foo,則PtrTo(t)表示* Foo。
*/
func PtrTo(t Type) Type {
return t.(*rtype).ptrTo()
}
/**
* ptrTo返回帶有元素t的指針類型。
*/
func (t *rtype) ptrTo() *rtype {
// 有ptrToThis,直接使用
if t.ptrToThis != 0 {
return t.typeOff(t.ptrToThis)
}
// Check the cache.
// 從緩存中取
if pi, ok := ptrMap.Load(t); ok {
return &pi.(*ptrType).rtype
}
// Look in known types.
// 查找已知類型。
s := "*" + t.String()
// typesByString返回typelinks()的子片段,其元素具有給定的字符串表示形式。
for _, tt := range typesByString(s) {
p := (*ptrType)(unsafe.Pointer(tt))
if p.elem != t {
continue
}
pi, _ := ptrMap.LoadOrStore(t, p)
return &pi.(*ptrType).rtype
}
// Create a new ptrType starting with the description
// of an *unsafe.Pointer.
// 從*unsafe.Pointer的描述開始創建一個新的ptrType。
var iptr interface{} = (*unsafe.Pointer)(nil)
prototype := *(**ptrType)(unsafe.Pointer(&iptr))
pp := *prototype
pp.str = resolveReflectName(newName(s, "", false))
pp.ptrToThis = 0
// For the type structures linked into the binary, the
// compiler provides a good hash of the string.
// Create a good hash for the new string by using
// the FNV-1 hash's mixing function to combine the
// old hash and the new "*".
// 對於鏈接到二進制文件中的類型結構,編譯器提供了字符串的良好哈希。
// 通過使用FNV-1哈希的混合函數爲舊字符串和新的“ *”組合,爲新字符串創建良好的哈希。
pp.hash = fnv1(t.hash, '*')
pp.elem = t
pi, _ := ptrMap.LoadOrStore(t, &pp)
return &pi.(*ptrType).rtype
}
// fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function.
/**
* fnv1使用FNV-1哈希函數將字節列表合併到哈希x中。
*/
func fnv1(x uint32, list ...byte) uint32 {
for _, b := range list {
x = x*16777619 ^ uint32(b)
}
return x
}
/**
* 當前類型是否實現接口u
*/
func (t *rtype) Implements(u Type) bool {
if u == nil {
panic("reflect: nil type passed to Type.Implements")
}
if u.Kind() != Interface {
panic("reflect: non-interface type passed to Type.Implements")
}
return implements(u.(*rtype), t)
}
/**
* 當前類型是否可賦值給類型u
*/
func (t *rtype) AssignableTo(u Type) bool {
if u == nil {
panic("reflect: nil type passed to Type.AssignableTo")
}
uu := u.(*rtype)
return directlyAssignable(uu, t) || implements(uu, t)
}
/**
* 當前類型是否可轉換成類型u
*/
func (t *rtype) ConvertibleTo(u Type) bool {
if u == nil {
panic("reflect: nil type passed to Type.ConvertibleTo")
}
uu := u.(*rtype)
return convertOp(uu, t) != nil
}
/**
* 當前類型是否可比較
*/
func (t *rtype) Comparable() bool {
return t.equal != nil
}
// implements reports whether the type V implements the interface type T.
/**
* 實現報告類型V是否實現接口類型T。
*/
func implements(T, V *rtype) bool {
if T.Kind() != Interface {
return false
}
t := (*interfaceType)(unsafe.Pointer(T))
if len(t.methods) == 0 {
return true
}
// The same algorithm applies in both cases, but the
// method tables for an interface type and a concrete type
// are different, so the code is duplicated.
// In both cases the algorithm is a linear scan over the two
// lists - T's methods and V's methods - simultaneously.
// Since method tables are stored in a unique sorted order
// (alphabetical, with no duplicate method names), the scan
// through V's methods must hit a match for each of T's
// methods along the way, or else V does not implement T.
// This lets us run the scan in overall linear time instead of
// the quadratic time a naive search would require.
// See also ../runtime/iface.go.
// 兩種情況下都應用相同的算法,但是接口類型和具體類型的方法表不同,因此代碼重複。
// 在這兩種情況下,算法都是同時對兩個列表(T方法和V方法)進行線性掃描。
// 由於方法表是以唯一的排序順序存儲的(字母順序,沒有重複的方法名稱),
// 因此對V方法的掃描必須沿途對每個T方法進行匹配,否則V不會實現T。
// 這樣,我們就可以在整個線性時間內(而不是天真的搜索所需的二次時間)運行掃描。
// 另請參閱../runtime/iface.go。
if V.Kind() == Interface { // V是接口類型
v := (*interfaceType)(unsafe.Pointer(V))
i := 0
for j := 0; j < len(v.methods); j++ {
tm := &t.methods[i]
tmName := t.nameOff(tm.name)
vm := &v.methods[j]
vmName := V.nameOff(vm.name)
// 名稱必須相同,typeOff是同樣的
if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
if !tmName.isExported() { // 非導出類型還要比較包名
tmPkgPath := tmName.pkgPath()
if tmPkgPath == "" {
tmPkgPath = t.pkgPath.name()
}
vmPkgPath := vmName.pkgPath()
if vmPkgPath == "" {
vmPkgPath = v.pkgPath.name()
}
if tmPkgPath != vmPkgPath {
continue
}
}
if i++; i >= len(t.methods) {
// 已經到了末尾
return true
}
}
}
return false
}
// V是非接口類型
v := V.uncommon()
if v == nil {
return false
}
i := 0
vmethods := v.methods()
for j := 0; j < int(v.mcount); j++ {
tm := &t.methods[i]
tmName := t.nameOff(tm.name)
vm := vmethods[j]
vmName := V.nameOff(vm.name)
if vmName.name() == tmName.name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
if !tmName.isExported() {
tmPkgPath := tmName.pkgPath()
if tmPkgPath == "" {
tmPkgPath = t.pkgPath.name()
}
vmPkgPath := vmName.pkgPath()
if vmPkgPath == "" {
vmPkgPath = V.nameOff(v.pkgPath).name()
}
if tmPkgPath != vmPkgPath {
continue
}
}
if i++; i >= len(t.methods) {
return true
}
}
}
return false
}
// specialChannelAssignability reports whether a value x of channel type V
// can be directly assigned (using memmove) to another channel type T.
// https://golang.org/doc/go_spec.html#Assignability
// T and V must be both of Chan kind.
/**
* specialChannelAssignability報告是否可以將通道類型V的值x直接(使用內存移動)分配給另一個通道類型T。
* https://golang.org/doc/go_spec.html#Assignability
* T和V必須都是Chan類型。
*/
func specialChannelAssignability(T, V *rtype) bool {
// Special case:
// x is a bidirectional channel value, T is a channel type,
// x's type V and T have identical element types,
// and at least one of V or T is not a defined type.
// 特殊情況:
// x是雙向通道值,T是通道類型,
// x的類型V和T具有相同的元素類型,
// 並且V或T中的至少一個不是定義的類型。
return V.ChanDir() == BothDir && (T.Name() == "" || V.Name() == "") && haveIdenticalType(T.Elem(), V.Elem(), true)
}
// directlyAssignable reports whether a value x of type V can be directly
// assigned (using memmove) to a value of type T.
// https://golang.org/doc/go_spec.html#Assignability
// Ignoring the interface rules (implemented elsewhere)
// and the ideal constant rules (no ideal constants at run time).
// directAssignable報告是否可以將V類型的值x直接(使用內存移動)分配給T類型的值。
// https://golang.org/doc/go_spec.html#Assignability
// 忽略接口規則(在其他地方實現)和理想常量規則(運行時沒有理想常量)。
func directlyAssignable(T, V *rtype) bool {
// x's type V is identical to T?
// x的V型與T相同
if T == V {
return true
}
// Otherwise at least one of T and V must not be defined
// and they must have the same kind.
// 都有名稱或者類型不同
if T.hasName() && V.hasName() || T.Kind() != V.Kind() {
return false
}
// 通道類型,並且通道可以賦值
if T.Kind() == Chan && specialChannelAssignability(T, V) {
return true
}
// x's type T and V must have identical underlying types.
// x的類型T和V必須具有相同的底層類型。
return haveIdenticalUnderlyingType(T, V, true)
}
/**
* 判斷是否類型一致
*/
func haveIdenticalType(T, V Type, cmpTags bool) bool {
if cmpTags {
return T == V
}
// 名稱不同或者類型不同
if T.Name() != V.Name() || T.Kind() != V.Kind() {
return false
}
// 判斷是否有相同的底層類型
return haveIdenticalUnderlyingType(T.common(), V.common(), false)
}
/**
* 判斷是否有相同的底層類型
*/
func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
if T == V {
return true
}
kind := T.Kind()
if kind != V.Kind() {
return false
}
// Non-composite types of equal kind have same underlying type
// (the predefined instance of the type).
// 相同種類的非複合類型具有相同的基礎類型(該類型的預定義實例)。
if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
return true
}
// Composite types.
// 組合類型
switch kind {
case Array: // 對於數組類型,長度要一致,元素類型要相同
return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
case Chan: // 通道類型一致,通道元素一致
return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
case Func: // 函數類型,出參入參要一致,並且對應參數類型要相同
t := (*funcType)(unsafe.Pointer(T))
v := (*funcType)(unsafe.Pointer(V))
if t.outCount != v.outCount || t.inCount != v.inCount {
return false
}
for i := 0; i < t.NumIn(); i++ {
if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
return false
}
}
for i := 0; i < t.NumOut(); i++ {
if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
return false
}
}
return true
case Interface: // 接口類型當沒有方法時,才類型一致
t := (*interfaceType)(unsafe.Pointer(T))
v := (*interfaceType)(unsafe.Pointer(V))
if len(t.methods) == 0 && len(v.methods) == 0 {
return true
}
// Might have the same methods but still
// need a run time conversion.
// 可能具有相同的方法,但仍需要運行時轉換。
return false
case Map: // 映射類型key和value類型都要致
return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
case Ptr, Slice: // 切片和指針類型,對應的元素類型必須一致
return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
case Struct: // 結構體類型,字段數,對應字段名稱,類型,標籤(如果需要),嵌入類型都要一致
t := (*structType)(unsafe.Pointer(T))
v := (*structType)(unsafe.Pointer(V))
if len(t.fields) != len(v.fields) {
return false
}
if t.pkgPath.name() != v.pkgPath.name() {
return false
}
for i := range t.fields {
tf := &t.fields[i]
vf := &v.fields[i]
if tf.name.name() != vf.name.name() {
return false
}
if !haveIdenticalType(tf.typ, vf.typ, cmpTags) {
return false
}
if cmpTags && tf.name.tag() != vf.name.tag() {
return false
}
if tf.offsetEmbed != vf.offsetEmbed {
return false
}
}
return true
}
return false
}
// typelinks is implemented in package runtime.
// It returns a slice of the sections in each module,
// and a slice of *rtype offsets in each module.
//
// The types in each module are sorted by string. That is, the first
// two linked types of the first module are:
//
// d0 := sections[0]
// t1 := (*rtype)(add(d0, offset[0][0]))
// t2 := (*rtype)(add(d0, offset[0][1]))
//
// and
//
// t1.String() < t2.String()
//
// Note that strings are not unique identifiers for types:
// there can be more than one with a given string.
// Only types we might want to look up are included:
// pointers, channels, maps, slices, and arrays.
/**
* typelinks在runtime包實現。在runtime/symtab.go文件中的
* moduledata中的typelinks,代表types的偏移量
* 它在每個模塊中返回一部分的切片,並在每個模塊中返回*rtype偏移量的切片。
*
* 每個模塊中的類型均按字符串排序。 即,第一個模塊的前兩個鏈接類型是:
*
* d0 := sections[0]
* t1 := (*rtype)(add(d0, offset[0][0]))
* t2 := (*rtype)(add(d0, offset[0][1]))
*
* 和
*
* t1.String() <t2.String()
*
* 注意,字符串不是類型的唯一標識符:給定的字符串可以有多個。
* 僅包括我們可能要查找的類型:指針,通道,映射,切片和數組。
*/
func typelinks() (sections []unsafe.Pointer, offset [][]int32)
/**
* 求指標的偏移量,並且返回rtype類型的打針
*/
func rtypeOff(section unsafe.Pointer, off int32) *rtype {
return (*rtype)(add(section, uintptr(off), "sizeof(rtype) > 0"))
}
// typesByString returns the subslice of typelinks() whose elements have
// the given string representation.
// It may be empty (no known types with that string) or may have
// multiple elements (multiple types with that string).
/**
* typesByString返回typelinks()的子片段,其元素具有給定的字符串表示形式。
* 它可能爲空(該字符串沒有已知類型)或可能具有多個元素(該字符串爲多個類型)。
* Question:
*/
func typesByString(s string) []*rtype {
sections, offset := typelinks()
var ret []*rtype
for offsI, offs := range offset {
section := sections[offsI]
// We are looking for the first index i where the string becomes >= s.
// This is a copy of sort.Search, with f(h) replaced by (*typ[h].String() >= s).
// 我們正在尋找第一個索引i,其中字符串變爲 >= s。
// 這是sort.Search的副本,其中f(h)替換爲(* typ [h] .String()> = s)。
// 二分查找,找滿足條件的索引最小的值
i, j := 0, len(offs)
for i < j {
h := i + (j-i)/2 // avoid overflow when computing h
// i ≤ h < j
if !(rtypeOff(section, offs[h]).String() >= s) {
i = h + 1 // preserves f(i-1) == false
} else {
j = h // preserves f(j) == true
}
}
// i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i.
// 當i == j, f(i-1) == false, 且 f(j) (= f(i)) == true ==> i是如找的值
// Having found the first, linear scan forward to find the last.
// We could do a second binary search, but the caller is going
// to do a linear scan anyway.
// 找到第一個線性向前掃描以找到最後一個。
// 我們可以進行第二次二進制搜索,但是調用者還是要進行線性掃描。
for j := i; j < len(offs); j++ {
typ := rtypeOff(section, offs[j])
if typ.String() != s { // 從i位置開始匹配,直到第一個類型不是爲止
break
}
ret = append(ret, typ)
}
}
return ret
}
// The lookupCache caches ArrayOf, ChanOf, MapOf and SliceOf lookups.
/**
* lookupCache緩存ArrayOf,ChanOf,MapOf和SliceOf查找結果。
*/
var lookupCache sync.Map // map[cacheKey]*rtype
// A cacheKey is the key for use in the lookupCache.
// Four values describe any of the types we are looking for:
// type kind, one or two subtypes, and an extra integer.
/**
* cacheKey是在lookupCache中使用的鍵。
* 四個值描述了我們正在尋找的任何類型:類型kind,一個或兩個子類型以及一個額外的整數。
*/
type cacheKey struct {
kind Kind
t1 *rtype
t2 *rtype
extra uintptr
}
// The funcLookupCache caches FuncOf lookups.
// FuncOf does not share the common lookupCache since cacheKey is not
// sufficient to represent functions unambiguously.
/**
* funcLookupCache緩存FuncOf查找結果。
* FuncOf不共享公共lookupCache,因爲cacheKey不足以明確表示函數。
*/
var funcLookupCache struct {
// 用於守位m
sync.Mutex // Guards stores (but not loads) on m.
// m is a map[uint32][]*rtype keyed by the hash calculated in FuncOf.
// Elements of m are append-only and thus safe for concurrent reading.
// m是一個map[uint32][]*rtype,由FuncOf中計算出的哈希值作爲鍵。
// m的元素是僅追加元素,因此對於並行讀取是安全的。
m sync.Map
}
// ChanOf returns the channel type with the given direction and element type.
// For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
//
// The gc runtime imposes a limit of 64 kB on channel element types.
// If t's size is equal to or exceeds this limit, ChanOf panics.
// ChanOf返回具有給定方向和元素類型的通道類型。
// 例如,如果t表示int,則ChanOf(RecvDir,t)表示<-chan int。
//
// gc運行時對通道元素類型施加64kB的限制。
// 如果t的大小等於或超過此限制,ChanOf會恐慌。
func ChanOf(dir ChanDir, t Type) Type {
typ := t.(*rtype)
// Look in cache.
// 在緩存中查找
ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
if ch, ok := lookupCache.Load(ckey); ok {
return ch.(*rtype)
}
// This restriction is imposed by the gc compiler and the runtime.
// 此限制由gc編譯器和運行時施加。
if typ.size >= 1<<16 { // 數據不能超過64kB
panic("reflect.ChanOf: element size too large")
}
// Look in known types.
// TODO: Precedence when constructing string.
// 查找已知類型。
// TODO:構造字符串時的優先級。
var s string
switch dir {
default:
panic("reflect.ChanOf: invalid dir")
case SendDir:
s = "chan<- " + typ.String()
case RecvDir:
s = "<-chan " + typ.String()
case BothDir:
s = "chan " + typ.String()
}
// 根據字符串描述獲取類型,並返回第一個在緩存中的值
for _, tt := range typesByString(s) {
ch := (*chanType)(unsafe.Pointer(tt))
if ch.elem == typ && ch.dir == uintptr(dir) {
ti, _ := lookupCache.LoadOrStore(ckey, tt)
return ti.(Type)
}
}
// Make a channel type.
// 創建一種通道類型
var ichan interface{} = (chan unsafe.Pointer)(nil)
prototype := *(**chanType)(unsafe.Pointer(&ichan))
ch := *prototype
ch.tflag = tflagRegularMemory
ch.dir = uintptr(dir)
ch.str = resolveReflectName(newName(s, "", false))
ch.hash = fnv1(typ.hash, 'c', byte(dir))
ch.elem = typ
ti, _ := lookupCache.LoadOrStore(ckey, &ch.rtype)
return ti.(Type)
}
// MapOf returns the map type with the given key and element types.
// For example, if k represents int and e represents string,
// MapOf(k, e) represents map[int]string.
//
// If the key type is not a valid map key type (that is, if it does
// not implement Go's == operator), MapOf panics.
/**
* MapOf返回具有給定鍵和元素類型的Map類型。
* 例如,如果k表示int而e表示字符串,則MapOfk, e)表示map[int]string。
*
* 如果鍵類型不是有效的Map鍵類型(即,如果它不實現Go的==運算符),則MapOf會發生恐慌。
*/
func MapOf(key, elem Type) Type {
ktyp := key.(*rtype)
etyp := elem.(*rtype)
if ktyp.equal == nil {
panic("reflect.MapOf: invalid key type " + ktyp.String())
}
// Look in cache.
// 在緩存中查找
ckey := cacheKey{Map, ktyp, etyp, 0}
if mt, ok := lookupCache.Load(ckey); ok {
return mt.(Type)
}
// Look in known types.
// 查找已知類型
s := "map[" + ktyp.String() + "]" + etyp.String()
for _, tt := range typesByString(s) {
mt := (*mapType)(unsafe.Pointer(tt))
if mt.key == ktyp && mt.elem == etyp {
ti, _ := lookupCache.LoadOrStore(ckey, tt)
return ti.(Type)
}
}
// Make a map type.
// Note: flag values must match those used in the TMAP case
// in ../cmd/compile/internal/gc/reflect.go:dtypesym.
// 設定Map類型。
// 注意:標誌值必須與../cmd/compile/internal/gc/reflect.go:dtypesym中TMAP情況下使用的標誌值匹配。
var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
mt := **(**mapType)(unsafe.Pointer(&imap))
mt.str = resolveReflectName(newName(s, "", false))
mt.tflag = 0
mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
mt.key = ktyp
mt.elem = etyp
mt.bucket = bucketOf(ktyp, etyp)
mt.hasher = func(p unsafe.Pointer, seed uintptr) uintptr {
return typehash(ktyp, p, seed)
}
mt.flags = 0
if ktyp.size > maxKeySize { // 超出了就是非直接key
mt.keysize = uint8(ptrSize)
mt.flags |= 1 // indirect key
} else {
mt.keysize = uint8(ktyp.size)
}
if etyp.size > maxValSize { // 超出了就是非直接value
mt.valuesize = uint8(ptrSize)
mt.flags |= 2 // indirect value
} else {
mt.valuesize = uint8(etyp.size)
}
mt.bucketsize = uint16(mt.bucket.size)
// isReflexive報告類型上的==操作是否是自反的。也就是說,對於類型t的所有值x,x == x。
if isReflexive(ktyp) {
mt.flags |= 4
}
// needKeyUpdate報告是否Map覆蓋要求複製key。
if needKeyUpdate(ktyp) {
mt.flags |= 8
}
// hashMightPanic報告類型爲t的映射鍵的哈希是否可能出現panic情況。
if hashMightPanic(ktyp) {
mt.flags |= 16
}
// 指向此類型的指針的類型,設置爲零
mt.ptrToThis = 0
ti, _ := lookupCache.LoadOrStore(ckey, &mt.rtype)
return ti.(Type)
}
// TODO(crawshaw): as these funcTypeFixedN structs have no methods,
// they could be defined at runtime using the StructOf function.
// TODO(crawshaw)::由於這些funcTypeFixedN結構沒有方法,因此可以在運行時使用StructOf函數定義它們。
// 一些固定參數的結構體類型
type funcTypeFixed4 struct {
funcType
args [4]*rtype
}
type funcTypeFixed8 struct {
funcType
args [8]*rtype
}
type funcTypeFixed16 struct {
funcType
args [16]*rtype
}
type funcTypeFixed32 struct {
funcType
args [32]*rtype
}
type funcTypeFixed64 struct {
funcType
args [64]*rtype
}
type funcTypeFixed128 struct {
funcType
args [128]*rtype
}
// FuncOf returns the function type with the given argument and result types.
// For example if k represents int and e represents string,
// FuncOf([]Type{k}, []Type{e}, false) represents func(int) string.
//
// The variadic argument controls whether the function is variadic. FuncOf
// panics if the in[len(in)-1] does not represent a slice and variadic is
// true.
/**
* FuncOf返回具有給定參數和結果類型的函數類型。
* 例如,如果k表示int,e表示字符串,則FuncOf([]Type{k}, []Type{e},false)表示func(int) string。
*
* variadic參數控制函數是否有可變參數。 如果in[len(in)-1]不代表切片並且可變參數爲true,則FuncOf會發生恐慌。
* @param in 入參
* @param out 出參
* @param variadic 否有可變參數
*/
func FuncOf(in, out []Type, variadic bool) Type {
// 有可變參數類型的情況下
if variadic && (len(in) == 0 || in[len(in)-1].Kind() != Slice) {
panic("reflect.FuncOf: last arg of variadic func must be slice")
}
// Make a func type.
// 創建函數類型
var ifunc interface{} = (func())(nil)
prototype := *(**funcType)(unsafe.Pointer(&ifunc))
n := len(in) + len(out) // 總參數個數
var ft *funcType
var args []*rtype
switch { // 根據總有參數個數創建對應類型
case n <= 4:
fixed := new(funcTypeFixed4)
args = fixed.args[:0:len(fixed.args)]
ft = &fixed.funcType
case n <= 8:
fixed := new(funcTypeFixed8)
args = fixed.args[:0:len(fixed.args)]
ft = &fixed.funcType
case n <= 16:
fixed := new(funcTypeFixed16)
args = fixed.args[:0:len(fixed.args)]
ft = &fixed.funcType
case n <= 32:
fixed := new(funcTypeFixed32)
args = fixed.args[:0:len(fixed.args)]
ft = &fixed.funcType
case n <= 64:
fixed := new(funcTypeFixed64)
args = fixed.args[:0:len(fixed.args)]
ft = &fixed.funcType
case n <= 128:
fixed := new(funcTypeFixed128)
args = fixed.args[:0:len(fixed.args)]
ft = &fixed.funcType
default:
panic("reflect.FuncOf: too many arguments")
}
*ft = *prototype
// Build a hash and minimally populate ft.
// 建立一個散列並最少填充ft。
var hash uint32
for _, in := range in {
t := in.(*rtype)
args = append(args, t)
hash = fnv1(hash, byte(t.hash>>24), byte(t.hash>>16), byte(t.hash>>8), byte(t.hash))
}
if variadic {
hash = fnv1(hash, 'v')
}
hash = fnv1(hash, '.')
for _, out := range out {
t := out.(*rtype)
args = append(args, t)
hash = fnv1(hash, byte(t.hash>>24), byte(t.hash>>16), byte(t.hash>>8), byte(t.hash))
}
// 參數過多
if len(args) > 50 {
panic("reflect.FuncOf does not support more than 50 arguments")
}
ft.tflag = 0 // 無額外類型信息
ft.hash = hash
ft.inCount = uint16(len(in))
ft.outCount = uint16(len(out))
if variadic { // 有可變參數,設置最高位
ft.outCount |= 1 << 15
}
// Look in cache.
// 在緩存中查找
if ts, ok := funcLookupCache.m.Load(hash); ok {
for _, t := range ts.([]*rtype) {
if haveIdenticalUnderlyingType(&ft.rtype, t, true) {
return t
}
}
}
// Not in cache, lock and retry.
// 如果緩存中沒有,就鎖住緩存,再次嘗試
funcLookupCache.Lock()
defer funcLookupCache.Unlock()
if ts, ok := funcLookupCache.m.Load(hash); ok {
for _, t := range ts.([]*rtype) {
if haveIdenticalUnderlyingType(&ft.rtype, t, true) {
return t
}
}
}
// 向緩存中添加函數的方法
addToCache := func(tt *rtype) Type {
var rts []*rtype
if rti, ok := funcLookupCache.m.Load(hash); ok {
rts = rti.([]*rtype)
}
funcLookupCache.m.Store(hash, append(rts, tt))
return tt
}
// Look in known types for the same string representation.
// 在已知類型中查找相同的字符串表示形式。
str := funcStr(ft)
for _, tt := range typesByString(str) {
if haveIdenticalUnderlyingType(&ft.rtype, tt, true) {
return addToCache(tt)
}
}
// Populate the remaining fields of ft and store in cache.
// 填充ft的其餘字段並存儲在緩存中。
ft.str = resolveReflectName(newName(str, "", false))
ft.ptrToThis = 0
// 向緩存中添加方法類型並且返回添加值
return addToCache(&ft.rtype)
}
// funcStr builds a string representation of a funcType.
/**
* funcStr構建funcType的字符串表示形式。輸出類似:func(int, string, ...bool) (int, string, ...bool)
*
* @param ft 函數類型
* @return funcType的字符串表示形式
**/
func funcStr(ft *funcType) string {
repr := make([]byte, 0, 64)
repr = append(repr, "func("...)
for i, t := range ft.in() { // 處理入參
if i > 0 {
repr = append(repr, ", "...)
}
if ft.IsVariadic() && i == int(ft.inCount)-1 { // 可變參數
repr = append(repr, "..."...)
repr = append(repr, (*sliceType)(unsafe.Pointer(t)).elem.String()...)
} else {
repr = append(repr, t.String()...)
}
}
repr = append(repr, ')')
// 處理出參
out := ft.out()
if len(out) == 1 {
repr = append(repr, ' ')
} else if len(out) > 1 {
repr = append(repr, " ("...)
}
for i, t := range out {
if i > 0 {
repr = append(repr, ", "...)
}
repr = append(repr, t.String()...)
}
if len(out) > 1 {
repr = append(repr, ')')
}
return string(repr)
}
// isReflexive reports whether the == operation on the type is reflexive.
// That is, x == x for all values x of type t.
/**
* isReflexive報告類型上的==操作是否自反。 也就是說,對於類型t的所有值x,x == x。
* @param t 類型
* @return true: ==操作是自反
* @date 2020-03-23 08:57:05
**/
func isReflexive(t *rtype) bool {
switch t.Kind() {
case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, String, UnsafePointer:
return true
case Float32, Float64, Complex64, Complex128, Interface:
return false
case Array: // 數組類型,判定子類型
tt := (*arrayType)(unsafe.Pointer(t))
return isReflexive(tt.elem)
case Struct: // 結構體類型,判斷所有的的字段類型
tt := (*structType)(unsafe.Pointer(t))
for _, f := range tt.fields {
if !isReflexive(f.typ) {
return false
}
}
return true
default:
// Func, Map, Slice, Invalid
panic("isReflexive called on non-key type " + t.String())
}
}
// needKeyUpdate reports whether map overwrites require the key to be copied.
/**
* needKeyUpdate報告Map覆蓋是否需要複製key。
* @param 類型
* @return true: Map覆蓋需要複製key
**/
func needKeyUpdate(t *rtype) bool {
switch t.Kind() {
case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, UnsafePointer:
return false
case Float32, Float64, Complex64, Complex128, Interface, String:
// Float keys can be updated from +0 to -0.
// String keys can be updated to use a smaller backing store.
// Interfaces might have floats of strings in them.
// float key可以從+0更新到-0。
// 可以將字符串鍵更新爲使用較小的後備存儲。
// 接口中可能包含字符串浮點數。
return true
case Array: // 數組類型,判定子類型
tt := (*arrayType)(unsafe.Pointer(t))
return needKeyUpdate(tt.elem)
case Struct: // 結構體類型,判斷所有的的字段類型
tt := (*structType)(unsafe.Pointer(t))
for _, f := range tt.fields {
if needKeyUpdate(f.typ) {
return true
}
}
return false
default:
// Func, Map, Slice, Invalid
panic("needKeyUpdate called on non-key type " + t.String())
}
}
// hashMightPanic reports whether the hash of a map key of type t might panic.
/**
* hashMightPanic報告類型爲t的Map key的哈希是否可能出現panic情況。
* @param
* @return
**/
func hashMightPanic(t *rtype) bool {
switch t.Kind() {
case Interface: // 接口類型會出現
return true
case Array: // 數組類型,判定子類型
tt := (*arrayType)(unsafe.Pointer(t))
return hashMightPanic(tt.elem)
case Struct: // 結構體類型,判斷所有的的字段類型
tt := (*structType)(unsafe.Pointer(t))
for _, f := range tt.fields {
if hashMightPanic(f.typ) {
return true
}
}
return false
default: // 其他必定不會出現
return false
}
}
// Make sure these routines stay in sync with ../../runtime/map.go!
// These types exist only for GC, so we only fill out GC relevant info.
// Currently, that's just size and the GC program. We also fill in string
// for possible debugging use.
/**
* 確保這些例程與../../runtime/map.go保持同步!
* 這些類型僅適用於GC,因此我們僅填寫與GC相關的信息。
* 當前,這只是大小和GC程序。 我們還填寫字符串以供可能的調試使用。
*/
const (
bucketSize uintptr = 8
maxKeySize uintptr = 128
maxValSize uintptr = 128
)
/**
* 創建桶類型
*/
func bucketOf(ktyp, etyp *rtype) *rtype {
if ktyp.size > maxKeySize {
ktyp = PtrTo(ktyp).(*rtype)
}
if etyp.size > maxValSize {
etyp = PtrTo(etyp).(*rtype)
}
// Prepare GC data if any.
// A bucket is at most bucketSize*(1+maxKeySize+maxValSize)+2*ptrSize bytes,
// or 2072 bytes, or 259 pointer-size words, or 33 bytes of pointer bitmap.
// Note that since the key and value are known to be <= 128 bytes,
// they're guaranteed to have bitmaps instead of GC programs.
/**
* 準備GC數據(如果有)。
* 一個存儲桶最多爲bucketSize*(1 + maxKeySize + maxValSize)+ 2 * ptrSize字節,
* 即2072字節,或259個指針大小的字,或33字節的指針bitmap。
* 請注意,由於已知鍵和值<= 128字節,因此可以確保它們具有bitmap而不是GC程序。
*/
var gcdata *byte
var ptrdata uintptr
var overflowPad uintptr
size := bucketSize*(1+ktyp.size+etyp.size) + overflowPad + ptrSize
if size&uintptr(ktyp.align-1) != 0 || size&uintptr(etyp.align-1) != 0 {
panic("reflect: bad size computation in MapOf")
}
if ktyp.ptrdata != 0 || etyp.ptrdata != 0 {
nptr := (bucketSize*(1+ktyp.size+etyp.size) + ptrSize) / ptrSize
mask := make([]byte, (nptr+7)/8)
base := bucketSize / ptrSize
if ktyp.ptrdata != 0 {
emitGCMask(mask, base, ktyp, bucketSize)
}
base += bucketSize * ktyp.size / ptrSize
if etyp.ptrdata != 0 {
emitGCMask(mask, base, etyp, bucketSize)
}
base += bucketSize * etyp.size / ptrSize
base += overflowPad / ptrSize
word := base
mask[word/8] |= 1 << (word % 8)
gcdata = &mask[0]
ptrdata = (word + 1) * ptrSize
// overflow word must be last
// 溢出字必須是最後一個
if ptrdata != size {
panic("reflect: bad layout computation in MapOf")
}
}
b := &rtype{
align: ptrSize,
size: size,
kind: uint8(Struct),
ptrdata: ptrdata,
gcdata: gcdata,
}
if overflowPad > 0 {
b.align = 8
}
s := "bucket(" + ktyp.String() + "," + etyp.String() + ")"
b.str = resolveReflectName(newName(s, "", false))
return b
}
/**
* 獲取gc字節切片
*/
func (t *rtype) gcSlice(begin, end uintptr) []byte {
return (*[1 << 30]byte)(unsafe.Pointer(t.gcdata))[begin:end:end]
}
// emitGCMask writes the GC mask for [n]typ into out, starting at bit
// offset base.
/**
* emitGCMask將[n] typ的GC掩碼從位偏移量的基數開始寫出到out中。
*/
func emitGCMask(out []byte, base uintptr, typ *rtype, n uintptr) {
if typ.kind&kindGCProg != 0 {
panic("reflect: unexpected GC program")
}
ptrs := typ.ptrdata / ptrSize
words := typ.size / ptrSize
mask := typ.gcSlice(0, (ptrs+7)/8)
for j := uintptr(0); j < ptrs; j++ {
if (mask[j/8]>>(j%8))&1 != 0 {
for i := uintptr(0); i < n; i++ {
k := base + i*words + j
out[k/8] |= 1 << (k % 8)
}
}
}
}
// appendGCProg appends the GC program for the first ptrdata bytes of
// typ to dst and returns the extended slice.
/**
* appendGCProg將typ的第一個ptrdata字節的GC程序追加到dst,並返回擴展的切片。
*/
func appendGCProg(dst []byte, typ *rtype) []byte {
if typ.kind&kindGCProg != 0 {
// Element has GC program; emit one element.
// 元素具有GC程序; 發出一個元素。
n := uintptr(*(*uint32)(unsafe.Pointer(typ.gcdata)))
prog := typ.gcSlice(4, 4+n-1)
return append(dst, prog...)
}
// Element is small with pointer mask; use as literal bits.
// 元素很小,帶有指針mask; 用作literal bits。
ptrs := typ.ptrdata / ptrSize
mask := typ.gcSlice(0, (ptrs+7)/8)
// Emit 120-bit chunks of full bytes (max is 127 but we avoid using partial bytes).
// 發射完整字節的120位塊(最大爲127,但我們避免使用部分字節)。
for ; ptrs > 120; ptrs -= 120 {
dst = append(dst, 120)
dst = append(dst, mask[:15]...)
mask = mask[15:]
}
dst = append(dst, byte(ptrs))
dst = append(dst, mask...)
return dst
}
// SliceOf returns the slice type with element type t.
// For example, if t represents int, SliceOf(t) represents []int.
/**
* SliceOf返回元素類型爲t的切片類型。
* 例如,如果t表示int,則SliceOf(t)表示[]int。
*/
func SliceOf(t Type) Type {
typ := t.(*rtype)
// Look in cache.
// 在緩存中查找。
ckey := cacheKey{Slice, typ, nil, 0}
if slice, ok := lookupCache.Load(ckey); ok {
return slice.(Type)
}
// Look in known types.
// 查找已知類型。
s := "[]" + typ.String()
for _, tt := range typesByString(s) {
slice := (*sliceType)(unsafe.Pointer(tt))
if slice.elem == typ {
ti, _ := lookupCache.LoadOrStore(ckey, tt)
return ti.(Type)
}
}
// Make a slice type.
// 創建一種切片類型
var islice interface{} = ([]unsafe.Pointer)(nil)
prototype := *(**sliceType)(unsafe.Pointer(&islice))
slice := *prototype
slice.tflag = 0
slice.str = resolveReflectName(newName(s, "", false))
slice.hash = fnv1(typ.hash, '[')
slice.elem = typ
slice.ptrToThis = 0
ti, _ := lookupCache.LoadOrStore(ckey, &slice.rtype)
return ti.(Type)
}
// The structLookupCache caches StructOf lookups.
// StructOf does not share the common lookupCache since we need to pin
// the memory associated with *structTypeFixedN.
/**
* structLookupCache緩存StructOf查找結果。
* StructOf不共享公共lookupCache,因爲我們需要固定與*structTypeFixedN關聯的內存。
*/
var structLookupCache struct {
sync.Mutex // Guards stores (but not loads) on m. // 用於守位m,Question: 具體怎麼守位
// m is a map[uint32][]Type keyed by the hash calculated in StructOf.
// Elements in m are append-only and thus safe for concurrent reading.
// m是一個Map [uint32] []類型,由在StructOf中計算出的哈希值作爲鍵。
// m中的元素是僅追加元素,因此可以安全地進行並行讀取。
m sync.Map
}
/**
* 結構體非平凡類型
*/
type structTypeUncommon struct {
structType
u uncommonType
}
// isLetter reports whether a given 'rune' is classified as a Letter.
/**
* isLetter報告給定的“符文”是否歸類爲字母。
*/
func isLetter(ch rune) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
}
// isValidFieldName checks if a string is a valid (struct) field name or not.
//
// According to the language spec, a field name should be an identifier.
//
// identifier = letter { letter | unicode_digit } .
// letter = unicode_letter | "_" .
/**
* isValidFieldName檢查字符串是否爲有效的(結構)字段名稱。
*
* 根據語言規範,字段名稱應爲標識符。
*
* 標識符 = 字母{字母|unicode數字}。
* 字母 = unicode字母|"_"。
*/
func isValidFieldName(fieldName string) bool {
for i, c := range fieldName {
if i == 0 && !isLetter(c) {
return false
}
if !(isLetter(c) || unicode.IsDigit(c)) {
return false
}
}
return len(fieldName) > 0
}
// StructOf returns the struct type containing fields.
// The Offset and Index fields are ignored and computed as they would be
// by the compiler.
//
// StructOf currently does not generate wrapper methods for embedded
// fields and panics if passed unexported StructFields.
// These limitations may be lifted in a future version.
/**
* StructOf返回包含字段的結構類型。
* 偏移量和索引字段將被忽略並按照編譯器的方式進行計算。
*
* StructOf當前不爲嵌入式字段生成包裝方法,並且如果傳遞未導出的StructFields,則會發生恐慌。
* 這些限制可能會在將來的版本中取消。
* TODO 需要進一步研究
*/
func StructOf(fields []StructField) Type {
var (
hash = fnv1(0, []byte("struct {")...)
size uintptr
typalign uint8 // 對齊類型
comparable = true
methods []method
fs = make([]structField, len(fields))
repr = make([]byte, 0, 64)
fset = map[string]struct{}{} // fields' names
hasGCProg = false // records whether a struct-field type has a GCProg // 記錄結構字段類型是否具有GCProg
)
lastzero := uintptr(0)
repr = append(repr, "struct {"...)
pkgpath := ""
for i, field := range fields { // 處理每一個字段
if field.Name == "" { // 字段名爲空
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
}
if !isValidFieldName(field.Name) { // 字段名不合法
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name")
}
if field.Type == nil { // 字段是nil類型
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
}
f, fpkgpath := runtimeStructField(field)
ft := f.typ
if ft.kind&kindGCProg != 0 {
hasGCProg = true
}
if fpkgpath != "" { // 獲取包路徑
if pkgpath == "" {
pkgpath = fpkgpath
} else if pkgpath != fpkgpath {
panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
}
}
// Update string and hash
// 更新字符串和哈希
name := f.name.name()
hash = fnv1(hash, []byte(name)...)
repr = append(repr, (" " + name)...)
if f.embedded() { // 如果是嵌入類型
// Embedded field
// 嵌入字段
if f.typ.Kind() == Ptr { // 是指針類型
// Embedded ** and *interface{} are illegal
// 嵌入式**和*interface{}是非法的
elem := ft.Elem()
// 元素類型不能是指針和接口
if k := elem.Kind(); k == Ptr || k == Interface {
panic("reflect.StructOf: illegal embedded field type " + ft.String())
}
}
switch f.typ.Kind() {
case Interface: // 接口類型
ift := (*interfaceType)(unsafe.Pointer(ft))
for im, m := range ift.methods { // 處理接口的每個方法
if ift.nameOff(m.name).pkgPath() != "" { // 包名爲空
// TODO(sbinet). Issue 15924.
panic("reflect: embedded interface with unexported method(s) not implemented")
}
var (
mtyp = ift.typeOff(m.typ)
ifield = i
imethod = im
ifn Value
tfn Value
)
if ft.kind&kindDirectIface != 0 {
tfn = MakeFunc(mtyp, func(in []Value) []Value {
var args []Value
var recv = in[0]
if len(in) > 1 {
args = in[1:]
}
return recv.Field(ifield).Method(imethod).Call(args)
})
ifn = MakeFunc(mtyp, func(in []Value) []Value {
var args []Value
var recv = in[0]
if len(in) > 1 {
args = in[1:]
}
return recv.Field(ifield).Method(imethod).Call(args)
})
} else {
tfn = MakeFunc(mtyp, func(in []Value) []Value {
var args []Value
var recv = in[0]
if len(in) > 1 {
args = in[1:]
}
return recv.Field(ifield).Method(imethod).Call(args)
})
ifn = MakeFunc(mtyp, func(in []Value) []Value {
var args []Value
var recv = Indirect(in[0])
if len(in) > 1 {
args = in[1:]
}
return recv.Field(ifield).Method(imethod).Call(args)
})
}
methods = append(methods, method{
name: resolveReflectName(ift.nameOff(m.name)),
mtyp: resolveReflectType(mtyp),
ifn: resolveReflectText(unsafe.Pointer(&ifn)),
tfn: resolveReflectText(unsafe.Pointer(&tfn)),
})
}
case Ptr: // 指針類型
ptr := (*ptrType)(unsafe.Pointer(ft))
if unt := ptr.uncommon(); unt != nil {
if i > 0 && unt.mcount > 0 {
// Issue 15924.
panic("reflect: embedded type with methods not implemented if type is not first field")
}
if len(fields) > 1 {
panic("reflect: embedded type with methods not implemented if there is more than one field")
}
for _, m := range unt.methods() {
mname := ptr.nameOff(m.name)
if mname.pkgPath() != "" {
// TODO(sbinet).
// Issue 15924.
panic("reflect: embedded interface with unexported method(s) not implemented")
}
methods = append(methods, method{
name: resolveReflectName(mname),
mtyp: resolveReflectType(ptr.typeOff(m.mtyp)),
ifn: resolveReflectText(ptr.textOff(m.ifn)),
tfn: resolveReflectText(ptr.textOff(m.tfn)),
})
}
}
if unt := ptr.elem.uncommon(); unt != nil {
for _, m := range unt.methods() {
mname := ptr.nameOff(m.name)
if mname.pkgPath() != "" {
// TODO(sbinet)
// Issue 15924.
panic("reflect: embedded interface with unexported method(s) not implemented")
}
methods = append(methods, method{
name: resolveReflectName(mname),
mtyp: resolveReflectType(ptr.elem.typeOff(m.mtyp)),
ifn: resolveReflectText(ptr.elem.textOff(m.ifn)),
tfn: resolveReflectText(ptr.elem.textOff(m.tfn)),
})
}
}
default:
if unt := ft.uncommon(); unt != nil {
if i > 0 && unt.mcount > 0 {
// Issue 15924.
panic("reflect: embedded type with methods not implemented if type is not first field")
}
if len(fields) > 1 && ft.kind&kindDirectIface != 0 {
panic("reflect: embedded type with methods not implemented for non-pointer type")
}
for _, m := range unt.methods() {
mname := ft.nameOff(m.name)
if mname.pkgPath() != "" {
// TODO(sbinet)
// Issue 15924.
panic("reflect: embedded interface with unexported method(s) not implemented")
}
methods = append(methods, method{
name: resolveReflectName(mname),
mtyp: resolveReflectType(ft.typeOff(m.mtyp)),
ifn: resolveReflectText(ft.textOff(m.ifn)),
tfn: resolveReflectText(ft.textOff(m.tfn)),
})
}
}
}
}
if _, dup := fset[name]; dup {
panic("reflect.StructOf: duplicate field " + name)
}
fset[name] = struct{}{}
hash = fnv1(hash, byte(ft.hash>>24), byte(ft.hash>>16), byte(ft.hash>>8), byte(ft.hash))
repr = append(repr, (" " + ft.String())...)
if f.name.tagLen() > 0 {
hash = fnv1(hash, []byte(f.name.tag())...)
repr = append(repr, (" " + strconv.Quote(f.name.tag()))...)
}
if i < len(fields)-1 {
repr = append(repr, ';')
}
comparable = comparable && (ft.equal != nil)
offset := align(size, uintptr(ft.align))
if ft.align > typalign {
typalign = ft.align
}
size = offset + ft.size
f.offsetEmbed |= offset << 1
if ft.size == 0 {
lastzero = size
}
fs[i] = f
}
if size > 0 && lastzero == size {
// This is a non-zero sized struct that ends in a
// zero-sized field. We add an extra byte of padding,
// to ensure that taking the address of the final
// zero-sized field can't manufacture a pointer to the
// next object in the heap. See issue 9401.
/**
* 這是一個非零大小的結構,以零大小的字段結尾。 我們添加了一個額外的填充字節,
* 以確保獲取最後一個零大小字段的地址不會產生指向堆中下一個對象的指針。
* 請參閱 issue 9401。
*/
size++
}
var typ *structType
var ut *uncommonType
if len(methods) == 0 {
t := new(structTypeUncommon)
typ = &t.structType
ut = &t.u
} else {
// A *rtype representing a struct is followed directly in memory by an
// array of method objects representing the methods attached to the
// struct. To get the same layout for a run time generated type, we
// need an array directly following the uncommonType memory.
// A similar strategy is used for funcTypeFixed4, ...funcTypeFixedN.
/**
* 代表結構的* rtype在內存中直接跟隨着表示附加到該結構的方法的方法對象數組。
* 爲了使運行時生成的類型具有相同的佈局,我們需要緊跟在uncommonType內存之後的數組。
* 類似的策略用於funcTypeFixed4,... funcTypeFixedN。
*/
tt := New(StructOf([]StructField{
{Name: "S", Type: TypeOf(structType{})},
{Name: "U", Type: TypeOf(uncommonType{})},
{Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))},
}))
typ = (*structType)(unsafe.Pointer(tt.Elem().Field(0).UnsafeAddr()))
ut = (*uncommonType)(unsafe.Pointer(tt.Elem().Field(1).UnsafeAddr()))
copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]method), methods)
}
// TODO(sbinet): Once we allow embedding multiple types,
// methods will need to be sorted like the compiler does.
// TODO(sbinet): Once we allow non-exported methods, we will
// need to compute xcount as the number of exported methods.
// TODO(sbinet): 一旦我們允許嵌入多個類型,就需要像編譯器一樣對方法進行排序。
// TODO(sbinet): 一旦允許非導出方法,我們將需要計算xcount作爲導出方法的數量。
ut.mcount = uint16(len(methods))
ut.xcount = ut.mcount
ut.moff = uint32(unsafe.Sizeof(uncommonType{}))
if len(fs) > 0 {
repr = append(repr, ' ')
}
repr = append(repr, '}')
hash = fnv1(hash, '}')
str := string(repr)
// Round the size up to be a multiple of the alignment.
// 將大小舍入爲對齊的倍數。
size = align(size, uintptr(typalign))
// Make the struct type.
var istruct interface{} = struct{}{}
prototype := *(**structType)(unsafe.Pointer(&istruct))
*typ = *prototype
typ.fields = fs
if pkgpath != "" {
typ.pkgPath = newName(pkgpath, "", false)
}
// Look in cache.
if ts, ok := structLookupCache.m.Load(hash); ok {
for _, st := range ts.([]Type) {
t := st.common()
if haveIdenticalUnderlyingType(&typ.rtype, t, true) {
return t
}
}
}
// Not in cache, lock and retry.
structLookupCache.Lock()
defer structLookupCache.Unlock()
if ts, ok := structLookupCache.m.Load(hash); ok {
for _, st := range ts.([]Type) {
t := st.common()
if haveIdenticalUnderlyingType(&typ.rtype, t, true) {
return t
}
}
}
addToCache := func(t Type) Type {
var ts []Type
if ti, ok := structLookupCache.m.Load(hash); ok {
ts = ti.([]Type)
}
structLookupCache.m.Store(hash, append(ts, t))
return t
}
// Look in known types.
for _, t := range typesByString(str) {
if haveIdenticalUnderlyingType(&typ.rtype, t, true) {
// even if 't' wasn't a structType with methods, we should be ok
// as the 'u uncommonType' field won't be accessed except when
// tflag&tflagUncommon is set.
// 即使't'不是帶有方法的structType,也應該沒問題,因爲除非設置了
// tflag&tflagUncommon,否則不會訪問'u uncommonType'字段。
return addToCache(t)
}
}
typ.str = resolveReflectName(newName(str, "", false))
typ.tflag = 0 // TODO: set tflagRegularMemory
typ.hash = hash
typ.size = size
typ.ptrdata = typeptrdata(typ.common())
typ.align = typalign
typ.fieldAlign = typalign
typ.ptrToThis = 0
if len(methods) > 0 {
typ.tflag |= tflagUncommon
}
if hasGCProg {
lastPtrField := 0
for i, ft := range fs {
if ft.typ.pointers() {
lastPtrField = i
}
}
prog := []byte{0, 0, 0, 0} // will be length of prog // 將是prog的長度
var off uintptr
for i, ft := range fs {
if i > lastPtrField {
// gcprog should not include anything for any field after
// the last field that contains pointer data
// gcprog不應在包含指針數據的最後一個字段之後的任何字段中包含任何內容
break
}
if !ft.typ.pointers() {
// Ignore pointerless fields.
// 忽略無指針字段。
continue
}
// Pad to start of this field with zeros.
// 用零填充該字段的開頭。
if ft.offset() > off {
n := (ft.offset() - off) / ptrSize
prog = append(prog, 0x01, 0x00) // emit a 0 bit // 發出0位
if n > 1 {
prog = append(prog, 0x81) // repeat previous bit // 重複上一位
prog = appendVarint(prog, n-1) // n-1 times
}
off = ft.offset()
}
prog = appendGCProg(prog, ft.typ)
off += ft.typ.ptrdata
}
prog = append(prog, 0)
*(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
typ.kind |= kindGCProg
typ.gcdata = &prog[0]
} else {
typ.kind &^= kindGCProg
bv := new(bitVector)
addTypeBits(bv, 0, typ.common())
if len(bv.data) > 0 {
typ.gcdata = &bv.data[0]
}
}
typ.equal = nil
if comparable {
typ.equal = func(p, q unsafe.Pointer) bool {
for _, ft := range typ.fields {
pi := add(p, ft.offset(), "&x.field safe")
qi := add(q, ft.offset(), "&x.field safe")
if !ft.typ.equal(pi, qi) {
return false
}
}
return true
}
}
switch {
case len(fs) == 1 && !ifaceIndir(fs[0].typ):
// structs of 1 direct iface type can be direct
typ.kind |= kindDirectIface
default:
typ.kind &^= kindDirectIface
}
return addToCache(&typ.rtype)
}
// runtimeStructField takes a StructField value passed to StructOf and
// returns both the corresponding internal representation, of type
// structField, and the pkgpath value to use for this field.
/**
* runtimeStructField接受傳遞給StructOf的StructField值,
* 並返回相應的內部表示形式structField和用於該字段的pkgpath值。
* @param
* @return
**/
func runtimeStructField(field StructField) (structField, string) {
// 無包名的匿名字段
if field.Anonymous && field.PkgPath != "" {
panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
}
exported := field.PkgPath == ""
if exported {
// Best-effort check for misuse.
// Since this field will be treated as exported, not much harm done if Unicode lowercase slips through.
// 盡最大努力檢查濫用情況。 由於此字段將被視爲導出字段,因此如果Unicode小寫漏掉,不會造成太大危害。
c := field.Name[0]
if 'a' <= c && c <= 'z' || c == '_' {
panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
}
}
offsetEmbed := uintptr(0)
if field.Anonymous {
offsetEmbed |= 1
}
resolveReflectType(field.Type.common()) // install in runtime
f := structField{
name: newName(field.Name, string(field.Tag), exported),
typ: field.Type.common(),
offsetEmbed: offsetEmbed,
}
return f, field.PkgPath
}
// typeptrdata returns the length in bytes of the prefix of t
// containing pointer data. Anything after this offset is scalar data.
// keep in sync with ../cmd/compile/internal/gc/reflect.go
/**
* typeptrdata返回包含指針數據的t前綴的長度(以字節爲單位)。
* 此偏移量之後的所有內容均爲標量數據。 與../cmd/compile/internal/gc/reflect.go保持同步
* @return 包含指針數據的t前綴的長度,此偏移量之後的所有內容均爲標量數據。
*/
func typeptrdata(t *rtype) uintptr {
switch t.Kind() {
case Struct:
st := (*structType)(unsafe.Pointer(t))
// find the last field that has pointers.
// 查找具有指針的最後一個字段。
field := -1
for i := range st.fields {
ft := st.fields[i].typ
if ft.pointers() {
field = i
}
}
if field == -1 {
return 0
}
f := st.fields[field]
return f.offset() + f.typ.ptrdata
default:
panic("reflect.typeptrdata: unexpected type, " + t.String())
}
}
// See cmd/compile/internal/gc/reflect.go for derivation of constant.
// 有關常量的派生,請參見cmd/compile/internal/gc/reflect.go。
const maxPtrmaskBytes = 2048
// ArrayOf returns the array type with the given count and element type.
// For example, if t represents int, ArrayOf(5, t) represents [5]int.
//
// If the resulting type would be larger than the available address space,
// ArrayOf panics.
/**
* ArrayOf返回具有給定計數和元素類型的數組類型。
* 例如,如果t表示int,則ArrayOf(5,t)表示[5] int。
*
* 如果結果類型大於可用的地址空間,
* ArrayOf恐慌。
*/
func ArrayOf(count int, elem Type) Type {
typ := elem.(*rtype)
// Look in cache.
// 在緩存中查找
ckey := cacheKey{Array, typ, nil, uintptr(count)}
if array, ok := lookupCache.Load(ckey); ok {
return array.(Type)
}
// Look in known types.
// 在已知類型中查找相同的字符串表示形式
s := "[" + strconv.Itoa(count) + "]" + typ.String()
for _, tt := range typesByString(s) {
array := (*arrayType)(unsafe.Pointer(tt))
if array.elem == typ {
ti, _ := lookupCache.LoadOrStore(ckey, tt)
return ti.(Type)
}
}
// Make an array type.
// 創建數組類型
var iarray interface{} = [1]unsafe.Pointer{}
prototype := *(**arrayType)(unsafe.Pointer(&iarray))
array := *prototype
array.tflag = typ.tflag & tflagRegularMemory
array.str = resolveReflectName(newName(s, "", false))
array.hash = fnv1(typ.hash, '[')
for n := uint32(count); n > 0; n >>= 8 {
array.hash = fnv1(array.hash, byte(n))
}
array.hash = fnv1(array.hash, ']')
array.elem = typ
array.ptrToThis = 0
if typ.size > 0 {
max := ^uintptr(0) / typ.size
if uintptr(count) > max { // 不能大於整個虛擬地址空間可表示的數組大小,虛擬地址空間根據機器的不同不一樣
panic("reflect.ArrayOf: array size would exceed virtual address space")
}
}
array.size = typ.size * uintptr(count) // 數組的大小
if count > 0 && typ.ptrdata != 0 { // 元素大於0,並且指針數據不爲0
// Question: 這個原理是什麼?
array.ptrdata = typ.size*uintptr(count-1) + typ.ptrdata
}
array.align = typ.align
array.fieldAlign = typ.fieldAlign
array.len = uintptr(count)
array.slice = SliceOf(elem).(*rtype)
switch {
case typ.ptrdata == 0 || array.size == 0: // 無指針或者數組長度爲0
// No pointers.
array.gcdata = nil
array.ptrdata = 0
case count == 1:
// In memory, 1-element array looks just like the element.
// 在內存中,1元素數組看起來就像元素。
array.kind |= typ.kind & kindGCProg
array.gcdata = typ.gcdata
array.ptrdata = typ.ptrdata
case typ.kind&kindGCProg == 0 && array.size <= maxPtrmaskBytes*8*ptrSize:
// Element is small with pointer mask; array is still small.
// Create direct pointer mask by turning each 1 bit in elem
// into count 1 bits in larger mask.
// 元素很小,帶有指針遮罩; 數組仍然很小。
// 通過將elem中的每個1位轉換爲較大掩碼中的1個位來創建直接指針掩碼。
mask := make([]byte, (array.ptrdata/ptrSize+7)/8)
emitGCMask(mask, 0, typ, array.len)
array.gcdata = &mask[0]
default:
// Create program that emits one element
// and then repeats to make the array.
// 創建發出一個元素然後重複進行以生成數組的程序。
prog := []byte{0, 0, 0, 0} // will be length of prog
prog = appendGCProg(prog, typ)
// Pad from ptrdata to size.
elemPtrs := typ.ptrdata / ptrSize
elemWords := typ.size / ptrSize
if elemPtrs < elemWords {
// Emit literal 0 bit, then repeat as needed.
prog = append(prog, 0x01, 0x00)
if elemPtrs+1 < elemWords {
prog = append(prog, 0x81)
prog = appendVarint(prog, elemWords-elemPtrs-1)
}
}
// Repeat count-1 times.
// 重複count-1次
if elemWords < 0x80 {
prog = append(prog, byte(elemWords|0x80))
} else {
prog = append(prog, 0x80)
prog = appendVarint(prog, elemWords)
}
prog = appendVarint(prog, uintptr(count)-1)
prog = append(prog, 0)
*(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4)
array.kind |= kindGCProg
array.gcdata = &prog[0]
// 高估但還可以 必須匹配程序
array.ptrdata = array.size // overestimate but ok; must match program
}
etyp := typ.common()
esize := etyp.Size()
array.equal = nil
if eequal := etyp.equal; eequal != nil {
array.equal = func(p, q unsafe.Pointer) bool {
for i := 0; i < count; i++ {
pi := arrayAt(p, i, esize, "i < count")
qi := arrayAt(q, i, esize, "i < count")
if !eequal(pi, qi) {
return false
}
}
return true
}
}
switch {
case count == 1 && !ifaceIndir(typ):
// array of 1 direct iface type can be direct
// 1個直接iface類型的數組可以是直接的
array.kind |= kindDirectIface
default:
array.kind &^= kindDirectIface
}
ti, _ := lookupCache.LoadOrStore(ckey, &array.rtype)
return ti.(Type)
}
func appendVarint(x []byte, v uintptr) []byte {
for ; v >= 0x80; v >>= 7 {
x = append(x, byte(v|0x80))
}
x = append(x, byte(v))
return x
}
// toType converts from a *rtype to a Type that can be returned
// to the client of package reflect. In gc, the only concern is that
// a nil *rtype must be replaced by a nil Type, but in gccgo this
// function takes care of ensuring that multiple *rtype for the same
// type are coalesced into a single Type.
/**
* toType從*rtype轉換爲可以返回給package反射客戶端的Type。
* 在gc中,唯一需要注意的是必須將nil *rtype替換爲nil Type,但是在gccgo中,
* 此函數將確保將同一類型的多個*rtype合併爲單個Type。
*/
func toType(t *rtype) Type {
if t == nil {
return nil
}
// Question: 沒有類型轉換,直接返回
return t
}
/**
* 函數類型的底層key
*/
type layoutKey struct {
ftyp *funcType // function signature // 函數簽名
rcvr *rtype // receiver type, or nil if none // 接收者類型
}
/**
* 函數類型的底層value
*/
type layoutType struct {
t *rtype
argSize uintptr // size of arguments // 參數大小,
retOffset uintptr // offset of return values. // 返回值的偏移量
stack *bitVector
framePool *sync.Pool
}
// 用於函數底層的緩存
var layoutCache sync.Map // map[layoutKey]layoutType
// funcLayout computes a struct type representing the layout of the
// function arguments and return values for the function type t.
// If rcvr != nil, rcvr specifies the type of the receiver.
// The returned type exists only for GC, so we only fill out GC relevant info.
// Currently, that's just size and the GC program. We also fill in
// the name for possible debugging use.
/**
* funcLayout計算一個表示函數參數佈局和函數類型t的返回值的結構類型。
* 如果rcvr != nil,則rcvr指定接收方的類型。
* 返回的類型僅適用於GC,因此我們僅填寫與GC相關的信息。
* 當前,這只是大小和GC程序。 我們還填寫該名稱,以供可能的調試使用。
* @param t 函數類型
* @param rcvr 接收者類型
* @return frametype 幀類型
* @return argSize 參數大小
* @return retOffset 返回值的偏移量
* @return stk 位向量
* @return framePool 幀的緩存池
*/
func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, argSize, retOffset uintptr, stk *bitVector, framePool *sync.Pool) {
if t.Kind() != Func { // 不是方法
panic("reflect: funcLayout of non-func type " + t.String())
}
if rcvr != nil && rcvr.Kind() == Interface { // 接收者不爲空,並且接收者是接口
panic("reflect: funcLayout with interface receiver " + rcvr.String())
}
k := layoutKey{t, rcvr}
if lti, ok := layoutCache.Load(k); ok {
lt := lti.(layoutType)
return lt.t, lt.argSize, lt.retOffset, lt.stack, lt.framePool
}
// compute gc program & stack bitmap for arguments
// 計算gc程序和堆棧位圖出參
ptrmap := new(bitVector)
var offset uintptr
if rcvr != nil {
// Reflect uses the "interface" calling convention for
// methods, where receivers take one word of argument
// space no matter how big they actually are.
// Reflect使用“接口”調用約定作爲方法,接收者無論實際大小如何都佔用一個參數空間。
if ifaceIndir(rcvr) || rcvr.pointers() { // 接口或者指針
ptrmap.append(1)
} else {
ptrmap.append(0)
}
offset += ptrSize // const ptrSize = 4 << (^uintptr(0) >> 63) ==> 0b00010000
}
// 處理入參
for _, arg := range t.in() {
offset += -offset & uintptr(arg.align-1)
addTypeBits(ptrmap, offset, arg)
offset += arg.size
}
argSize = offset
offset += -offset & (ptrSize - 1)
retOffset = offset
for _, res := range t.out() {
offset += -offset & uintptr(res.align-1)
addTypeBits(ptrmap, offset, res)
offset += res.size
}
offset += -offset & (ptrSize - 1)
// build dummy rtype holding gc program
// 建立虛擬rtype持有gc程序
x := &rtype{
align: ptrSize,
size: offset,
ptrdata: uintptr(ptrmap.n) * ptrSize,
}
if ptrmap.n > 0 {
x.gcdata = &ptrmap.data[0]
}
var s string
if rcvr != nil {
s = "methodargs(" + rcvr.String() + ")(" + t.String() + ")"
} else {
s = "funcargs(" + t.String() + ")"
}
x.str = resolveReflectName(newName(s, "", false))
// cache result for future callers
// 緩存結果以供將來的使用
framePool = &sync.Pool{New: func() interface{} {
return unsafe_New(x)
}}
lti, _ := layoutCache.LoadOrStore(k, layoutType{
t: x,
argSize: argSize,
retOffset: retOffset,
stack: ptrmap,
framePool: framePool,
})
lt := lti.(layoutType)
return lt.t, lt.argSize, lt.retOffset, lt.stack, lt.framePool
}
// ifaceIndir reports whether t is stored indirectly in an interface value.
/**
* ifaceIndir報告t是否間接存儲在接口值中。
*/
func ifaceIndir(t *rtype) bool {
return t.kind&kindDirectIface == 0
}
// 位向量
type bitVector struct {
n uint32 // number of bits // 位數
data []byte
}
// append a bit to the bitmap.
// 向位圖中添加一個位,uint8其實只使用了最低位,值爲0或者1
func (bv *bitVector) append(bit uint8) {
if bv.n%8 == 0 { // 位剛好用完了,擴容一個字節
bv.data = append(bv.data, 0)
}
bv.data[bv.n/8] |= bit << (bv.n % 8) // 將位添加到指定位置
bv.n++
}
/**
* 爲類型t添加位信息到位圖bv中
*/
func addTypeBits(bv *bitVector, offset uintptr, t *rtype) {
if t.ptrdata == 0 {
return
}
switch Kind(t.kind & kindMask) {
case Chan, Func, Map, Ptr, Slice, String, UnsafePointer:
// 1 pointer at start of representation
// 表示開始時有1個指針
for bv.n < uint32(offset/uintptr(ptrSize)) {
bv.append(0)
}
bv.append(1)
case Interface:
// 2 pointers
// 兩個指針
for bv.n < uint32(offset/uintptr(ptrSize)) {
bv.append(0)
}
bv.append(1)
bv.append(1)
case Array:
// repeat inner type
// 遞歸處理每個元素
tt := (*arrayType)(unsafe.Pointer(t))
for i := 0; i < int(tt.len); i++ {
addTypeBits(bv, offset+uintptr(i)*tt.elem.size, tt.elem)
}
case Struct:
// apply fields
// 遞歸處理每個字段
tt := (*structType)(unsafe.Pointer(t))
for i := range tt.fields {
f := &tt.fields[i]
addTypeBits(bv, offset+f.offset(), f.typ)
}
}
}