🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# package reflect `import "reflect"` reflect包实现了运行时反射,允许程序操作任意类型的对象。典型用法是用静态类型interface{}保存一个值,通过调用TypeOf获取其动态类型信息,该函数返回一个Type类型值。调用ValueOf函数返回一个Value类型值,该值代表运行时的数据。Zero接受一个Type类型参数并返回一个代表该类型零值的Value类型值。 参见"The Laws of Reflection"获取go反射的介绍:[http://golang.org/doc/articles/laws_of_reflection.html](http://golang.org/doc/articles/laws_of_reflection.html) ## Index * [Constants](#pkg-constants) * [type ValueError](#ValueError) * [func (e \*ValueError) Error() string](#ValueError.Error) * [type Kind](#Kind) * [func (k Kind) String() string](#Kind.String) * [type StringHeader](#StringHeader) * [type SliceHeader](#SliceHeader) * [type StructField](#StructField) * [type StructTag](#StructTag) * [func (tag StructTag) Get(key string) string](#StructTag.Get) * [type ChanDir](#ChanDir) * [func (d ChanDir) String() string](#ChanDir.String) * [type SelectDir](#SelectDir) * [type SelectCase](#SelectCase) * [func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool)](#Select) * [type Method](#Method) * [type Type](#Type) * [func TypeOf(i interface{}) Type](#TypeOf) * [func PtrTo(t Type) Type](#PtrTo) * [func SliceOf(t Type) Type](#SliceOf) * [func MapOf(key, elem Type) Type](#MapOf) * [func ChanOf(dir ChanDir, t Type) Type](#ChanOf) * [type Value](#Value) * [func ValueOf(i interface{}) Value](#ValueOf) * [func Zero(typ Type) Value](#Zero) * [func New(typ Type) Value](#New) * [func NewAt(typ Type, p unsafe.Pointer) Value](#NewAt) * [func Indirect(v Value) Value](#Indirect) * [func MakeSlice(typ Type, len, cap int) Value](#MakeSlice) * [func MakeMap(typ Type) Value](#MakeMap) * [func MakeChan(typ Type, buffer int) Value](#MakeChan) * [func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value](#MakeFunc) * [func Append(s Value, x ...Value) Value](#Append) * [func AppendSlice(s, t Value) Value](#AppendSlice) * [func (v Value) IsValid() bool](#Value.IsValid) * [func (v Value) IsNil() bool](#Value.IsNil) * [func (v Value) Kind() Kind](#Value.Kind) * [func (v Value) Type() Type](#Value.Type) * [func (v Value) Convert(t Type) Value](#Value.Convert) * [func (v Value) Elem() Value](#Value.Elem) * [func (v Value) Bool() bool](#Value.Bool) * [func (v Value) Int() int64](#Value.Int) * [func (v Value) OverflowInt(x int64) bool](#Value.OverflowInt) * [func (v Value) Uint() uint64](#Value.Uint) * [func (v Value) OverflowUint(x uint64) bool](#Value.OverflowUint) * [func (v Value) Float() float64](#Value.Float) * [func (v Value) OverflowFloat(x float64) bool](#Value.OverflowFloat) * [func (v Value) Complex() complex128](#Value.Complex) * [func (v Value) OverflowComplex(x complex128) bool](#Value.OverflowComplex) * [func (v Value) Bytes() []byte](#Value.Bytes) * [func (v Value) String() string](#Value.String) * [func (v Value) Pointer() uintptr](#Value.Pointer) * [func (v Value) InterfaceData() [2]uintptr](#Value.InterfaceData) * [func (v Value) Slice(i, j int) Value](#Value.Slice) * [func (v Value) Slice3(i, j, k int) Value](#Value.Slice3) * [func (v Value) Cap() int](#Value.Cap) * [func (v Value) Len() int](#Value.Len) * [func (v Value) Index(i int) Value](#Value.Index) * [func (v Value) MapIndex(key Value) Value](#Value.MapIndex) * [func (v Value) MapKeys() []Value](#Value.MapKeys) * [func (v Value) NumField() int](#Value.NumField) * [func (v Value) Field(i int) Value](#Value.Field) * [func (v Value) FieldByIndex(index []int) Value](#Value.FieldByIndex) * [func (v Value) FieldByName(name string) Value](#Value.FieldByName) * [func (v Value) FieldByNameFunc(match func(string) bool) Value](#Value.FieldByNameFunc) * [func (v Value) Recv() (x Value, ok bool)](#Value.Recv) * [func (v Value) TryRecv() (x Value, ok bool)](#Value.TryRecv) * [func (v Value) Send(x Value)](#Value.Send) * [func (v Value) TrySend(x Value) bool](#Value.TrySend) * [func (v Value) Close()](#Value.Close) * [func (v Value) Call(in []Value) []Value](#Value.Call) * [func (v Value) CallSlice(in []Value) []Value](#Value.CallSlice) * [func (v Value) NumMethod() int](#Value.NumMethod) * [func (v Value) Method(i int) Value](#Value.Method) * [func (v Value) MethodByName(name string) Value](#Value.MethodByName) * [func (v Value) CanAddr() bool](#Value.CanAddr) * [func (v Value) Addr() Value](#Value.Addr) * [func (v Value) UnsafeAddr() uintptr](#Value.UnsafeAddr) * [func (v Value) CanInterface() bool](#Value.CanInterface) * [func (v Value) Interface() (i interface{})](#Value.Interface) * [func (v Value) CanSet() bool](#Value.CanSet) * [func (v Value) SetBool(x bool)](#Value.SetBool) * [func (v Value) SetInt(x int64)](#Value.SetInt) * [func (v Value) SetUint(x uint64)](#Value.SetUint) * [func (v Value) SetFloat(x float64)](#Value.SetFloat) * [func (v Value) SetComplex(x complex128)](#Value.SetComplex) * [func (v Value) SetBytes(x []byte)](#Value.SetBytes) * [func (v Value) SetString(x string)](#Value.SetString) * [func (v Value) SetPointer(x unsafe.Pointer)](#Value.SetPointer) * [func (v Value) SetCap(n int)](#Value.SetCap) * [func (v Value) SetLen(n int)](#Value.SetLen) * [func (v Value) SetMapIndex(key, val Value)](#Value.SetMapIndex) * [func (v Value) Set(x Value)](#Value.Set) * [func Copy(dst, src Value) int](#Copy) * [func DeepEqual(a1, a2 interface{}) bool](#DeepEqual) ### Examples * [MakeFunc](#example-MakeFunc) * [StructTag](#example-StructTag) ## Constants ``` const ( SelectSend // case Chan <- Send SelectRecv // case <-Chan: SelectDefault // default ) ``` ## type [ValueError](https://github.com/golang/go/blob/master/src/reflect/value.go#L187 "View Source") ``` type ValueError struct { Method string Kind Kind } ``` 当一个Value类型值调用它不支持的方法时,将导致ValueError。具体情况参见各个方法。 ### func (\*ValueError) [Error](https://github.com/golang/go/blob/master/src/reflect/value.go#L192 "View Source") ``` func (e *ValueError) Error() string ``` ## type [Kind](https://github.com/golang/go/blob/master/src/reflect/type.go#L208 "View Source") ``` type Kind uint ``` Kind代表Type类型值表示的具体分类。零值表示非法分类。 ``` 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 ) ``` ### func (Kind) [String](https://github.com/golang/go/blob/master/src/reflect/type.go#L406 "View Source") ``` func (k Kind) String() string ``` ## type [StringHeader](https://github.com/golang/go/blob/master/src/reflect/value.go#L1914 "View Source") ``` type StringHeader struct { Data uintptr Len int } ``` StringHeader代表一个运行时的字符串。它不保证使用的可移植性、安全性;它的实现在未来的版本里也可能会改变。而且,Data字段也不能保证它指向的数据不会被当成垃圾收集,因此程序必须维护一个独立的、类型正确的指向底层数据的指针。 ## type [SliceHeader](https://github.com/golang/go/blob/master/src/reflect/value.go#L1931 "View Source") ``` type SliceHeader struct { Data uintptr Len int Cap int } ``` SliceHeader代表一个运行时的切片。它不保证使用的可移植性、安全性;它的实现在未来的版本里也可能会改变。而且,Data字段也不能保证它指向的数据不会被当成垃圾收集,因此程序必须维护一个独立的、类型正确的指向底层数据的指针。 ## type [StructField](https://github.com/golang/go/blob/master/src/reflect/type.go#L734 "View Source") ``` type StructField struct { // Name是字段的名字。PkgPath是非导出字段的包路径,对导出字段该字段为""。 // 参见http://golang.org/ref/spec#Uniqueness_of_identifiers Name string PkgPath string Type Type // 字段的类型 Tag StructTag // 字段的标签 Offset uintptr // 字段在结构体中的字节偏移量 Index []int // 用于Type.FieldByIndex时的索引切片 Anonymous bool // 是否匿名字段 } ``` StructField类型描述结构体中的一个字段的信息。 ## type [StructTag](https://github.com/golang/go/blob/master/src/reflect/type.go#L757 "View Source") ``` type StructTag string ``` StructTag是结构体字段的标签。 一般来说,标签字符串是(可选的)空格分隔的一连串`key:"value"`对。每个键都是不包含控制字符、空格、双引号、冒号的非空字符串。每个值都应被双引号括起来,使用go字符串字面语法。 Example ``` type S struct { F string `species:"gopher" color:"blue"` } s := S{} st := reflect.TypeOf(s) field := st.Field(0) fmt.Println(field.Tag.Get("color"), field.Tag.Get("species")) ``` Output: ``` blue gopher ``` ### func (StructTag) [Get](https://github.com/golang/go/blob/master/src/reflect/type.go#L763 "View Source") ``` func (tag StructTag) Get(key string) string ``` Get方法返回标签字符串中键key对应的值。如果标签中没有该键,会返回""。如果标签不符合标准格式,Get的返回值是不确定的。 ## type [ChanDir](https://github.com/golang/go/blob/master/src/reflect/type.go#L280 "View Source") ``` type ChanDir int ``` ChanDir表示通道类型的方向。 ``` const ( RecvDir ChanDir = 1 << iota // <-chan SendDir // chan<- BothDir = RecvDir | SendDir // chan ) ``` ### func (ChanDir) [String](https://github.com/golang/go/blob/master/src/reflect/type.go#L688 "View Source") ``` func (d ChanDir) String() string ``` ## type [SelectDir](https://github.com/golang/go/blob/master/src/reflect/value.go#L2074 "View Source") ``` type SelectDir int ``` SelectDir描述一个SelectCase的通信方向。 ## type [SelectCase](https://github.com/golang/go/blob/master/src/reflect/value.go#L2102 "View Source") ``` type SelectCase struct { Dir SelectDir // case的方向 Chan Value // 使用的通道(收/发) Send Value // 用于发送的值 } ``` SelectCase描述select操作中的单条case。Case的类型由通信方向Dir决定。 如果Dir是SelectDefault,该条case代表default case。Chan和Send字段必须是Value零值。 如果Dir是SelectSend,该条case代表一个发送操作。Chan字段底层必须是一个chan类型,Send的底层必须是可以直接赋值给该chan类型成员类型的类型。如果Chan是Value零值,则不管Send字段是不是零值,该条case都会被忽略。 如果Dir是SelectRecv,该条case代表一个接收操作。Chan字段底层必须是一个chan类型,而Send必须是一个Value零值。如果Chan是Value零值,该条case会被忽略,但Send字段仍需是Value零值。当该条case被执行时,接收到的值会被Select返回。 ## func [Select](https://github.com/golang/go/blob/master/src/reflect/value.go#L2115 "View Source") ``` func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) ``` Select函数执行cases切片描述的select操作。 类似go的select语句,它会阻塞直到至少一条case可以执行,从可执行的case中(伪)随机的选择一条,并执行该条case。它会返回选择执行的case的索引,以及如果执行的是接收case时,会返回接收到的值,以及一个布尔值说明该值是否对应于通道中某次发送的值(用以区分通道关闭时接收到的零值,此时recvOK会设为false)。 ## type [Method](https://github.com/golang/go/blob/master/src/reflect/type.go#L384 "View Source") ``` type Method struct { // Name是方法名。PkgPath是非导出字段的包路径,对导出字段该字段为""。 // 结合PkgPath和Name可以从方法集中指定一个方法。 // 参见http://golang.org/ref/spec#Uniqueness_of_identifiers Name string PkgPath string Type Type // 方法类型 Func Value // 方法的值 Index int // 用于Type.Method的索引 } ``` Method代表一个方法。 ## type [Type](https://github.com/golang/go/blob/master/src/reflect/type.go#L32 "View Source") ``` type Type interface { // Kind返回该接口的具体分类 Kind() Kind // Name返回该类型在自身包内的类型名,如果是未命名类型会返回"" Name() string // PkgPath返回类型的包路径,即明确指定包的import路径,如"encoding/base64" // 如果类型为内建类型(string, error)或未命名类型(*T, struct{}, []int),会返回"" PkgPath() string // 返回类型的字符串表示。该字符串可能会使用短包名(如用base64代替"encoding/base64") // 也不保证每个类型的字符串表示不同。如果要比较两个类型是否相等,请直接用Type类型比较。 String() string // 返回要保存一个该类型的值需要多少字节;类似unsafe.Sizeof Size() uintptr // 返回当从内存中申请一个该类型值时,会对齐的字节数 Align() int // 返回当该类型作为结构体的字段时,会对齐的字节数 FieldAlign() int // 如果该类型实现了u代表的接口,会返回真 Implements(u Type) bool // 如果该类型的值可以直接赋值给u代表的类型,返回真 AssignableTo(u Type) bool // 如该类型的值可以转换为u代表的类型,返回真 ConvertibleTo(u Type) bool // 返回该类型的字位数。如果该类型的Kind不是Int、Uint、Float或Complex,会panic Bits() int // 返回array类型的长度,如非数组类型将panic Len() int // 返回该类型的元素类型,如果该类型的Kind不是Array、Chan、Map、Ptr或Slice,会panic Elem() Type // 返回map类型的键的类型。如非映射类型将panic Key() Type // 返回一个channel类型的方向,如非通道类型将会panic ChanDir() ChanDir // 返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panic NumField() int // 返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic Field(i int) StructField // 返回索引序列指定的嵌套字段的类型, // 等价于用索引中每个值链式调用本方法,如非结构体将会panic FieldByIndex(index []int) StructField // 返回该类型名为name的字段(会查找匿名字段及其子字段), // 布尔值说明是否找到,如非结构体将panic FieldByName(name string) (StructField, bool) // 返回该类型第一个字段名满足函数match的字段,布尔值说明是否找到,如非结构体将会panic FieldByNameFunc(match func(string) bool) (StructField, bool) // 如果函数类型的最后一个输入参数是"..."形式的参数,IsVariadic返回真 // 如果这样,t.In(t.NumIn() - 1)返回参数的隐式的实际类型(声明类型的切片) // 如非函数类型将panic IsVariadic() bool // 返回func类型的参数个数,如果不是函数,将会panic NumIn() int // 返回func类型的第i个参数的类型,如非函数或者i不在[0, NumIn())内将会panic In(i int) Type // 返回func类型的返回值个数,如果不是函数,将会panic NumOut() int // 返回func类型的第i个返回值的类型,如非函数或者i不在[0, NumOut())内将会panic Out(i int) Type // 返回该类型的方法集中方法的数目 // 匿名字段的方法会被计算;主体类型的方法会屏蔽匿名字段的同名方法; // 匿名字段导致的歧义方法会滤除 NumMethod() int // 返回该类型方法集中的第i个方法,i不在[0, NumMethod())范围内时,将导致panic // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态 // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil Method(int) Method // 根据方法名返回该类型方法集中的方法,使用一个布尔值说明是否发现该方法 // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态 // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil MethodByName(string) (Method, bool) // 内含隐藏或非导出方法 } ``` Type类型用来表示一个go类型。 不是所有go类型的Type值都能使用所有方法。请参见每个方法的文档获取使用限制。在调用有分类限定的方法时,应先使用Kind方法获知类型的分类。调用该分类不支持的方法会导致运行时的panic。 ### func [TypeOf](https://github.com/golang/go/blob/master/src/reflect/type.go#L1005 "View Source") ``` func TypeOf(i interface{}) Type ``` TypeOf返回接口中保存的值的类型,TypeOf(nil)会返回nil。 ### func [PtrTo](https://github.com/golang/go/blob/master/src/reflect/type.go#L1044 "View Source") ``` func PtrTo(t Type) Type ``` PtrTo返回类型t的指针的类型。 ### func [SliceOf](https://github.com/golang/go/blob/master/src/reflect/type.go#L1702 "View Source") ``` func SliceOf(t Type) Type ``` SliceOf返回类型t的切片的类型。 ### func [MapOf](https://github.com/golang/go/blob/master/src/reflect/type.go#L1507 "View Source") ``` func MapOf(key, elem Type) Type ``` MapOf返回一个键类型为key,值类型为elem的映射类型。如果key代表的类型不是合法的映射键类型(即它未实现go的==操作符),本函数会panic。 ### func [ChanOf](https://github.com/golang/go/blob/master/src/reflect/type.go#L1437 "View Source") ``` func ChanOf(dir ChanDir, t Type) Type ``` ChanOf返回元素类型为t、方向为dir的通道类型。运行时GC强制将通道的元素类型的大小限定为64kb。如果t的尺寸大于或等于该限制,本函数将会panic。 ## type [Value](https://github.com/golang/go/blob/master/src/reflect/value.go#L61 "View Source") ``` type Value struct { // 内含隐藏或非导出字段 } ``` Value为go值提供了反射接口。 不是所有go类型值的Value表示都能使用所有方法。请参见每个方法的文档获取使用限制。在调用有分类限定的方法时,应先使用Kind方法获知该值的分类。调用该分类不支持的方法会导致运行时的panic。 Value类型的零值表示不持有某个值。零值的IsValid方法返回false,其Kind方法返回Invalid,而String方法返回"&lt;invalid Value&gt;",所有其它方法都会panic。绝大多数函数和方法都永远不返回Value零值。如果某个函数/方法返回了非法的Value,它的文档必须显式的说明具体情况。 如果某个go类型值可以安全的用于多线程并发操作,它的Value表示也可以安全的用于并发。 ### func [ValueOf](https://github.com/golang/go/blob/master/src/reflect/value.go#L2268 "View Source") ``` func ValueOf(i interface{}) Value ``` ValueOf返回一个初始化为i接口保管的具体值的Value,ValueOf(nil)返回Value零值。 ### func [Zero](https://github.com/golang/go/blob/master/src/reflect/value.go#L2288 "View Source") ``` func Zero(typ Type) Value ``` Zero返回一个持有类型typ的零值的Value。注意持有零值的Value和Value零值是两回事。Value零值表示不持有任何值。例如Zero(TypeOf(42))返回一个Kind为Int、值为0的Value。Zero的返回值不能设置也不会寻址。 ### func [New](https://github.com/golang/go/blob/master/src/reflect/value.go#L2302 "View Source") ``` func New(typ Type) Value ``` New返回一个Value类型值,该值持有一个指向类型为typ的新申请的零值的指针,返回值的Type为PtrTo(typ)。 ### func [NewAt](https://github.com/golang/go/blob/master/src/reflect/value.go#L2313 "View Source") ``` func NewAt(typ Type, p unsafe.Pointer) Value ``` NewAt返回一个Value类型值,该值持有一个指向类型为typ、地址为p的值的指针。 ### func [Indirect](https://github.com/golang/go/blob/master/src/reflect/value.go#L2259 "View Source") ``` func Indirect(v Value) Value ``` 返回持有v持有的指针指向的值的Value。如果v持有nil指针,会返回Value零值;如果v不持有指针,会返回v。 ### func [MakeSlice](https://github.com/golang/go/blob/master/src/reflect/value.go#L2214 "View Source") ``` func MakeSlice(typ Type, len, cap int) Value ``` MakeSlice创建一个新申请的元素类型为typ,长度len容量cap的切片类型的Value值。 ### func [MakeMap](https://github.com/golang/go/blob/master/src/reflect/value.go#L2248 "View Source") ``` func MakeMap(typ Type) Value ``` MakeMap创建一个特定映射类型的Value值。 ### func [MakeChan](https://github.com/golang/go/blob/master/src/reflect/value.go#L2233 "View Source") ``` func MakeChan(typ Type, buffer int) Value ``` MakeChan创建一个元素类型为typ、有buffer个缓存的通道类型的Value值。 ### func [MakeFunc](https://github.com/golang/go/blob/master/src/reflect/makefunc.go#L43 "View Source") ``` func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value ``` MakeFunc返回一个具有给定类型、包装函数fn的函数的Value封装。当被调用时,该函数会: ``` - 将提供给它的参数转化为Value切片 - 执行results := fn(args) - 将results中每一个result依次排列作为返回值 ``` 函数fn的实现可以假设参数Value切片匹配typ类型指定的参数数目和类型。如果typ表示一个可变参数函数类型,参数切片中最后一个Value本身必须是一个包含所有可变参数的切片。fn返回的结果Value切片也必须匹配typ类型指定的结果数目和类型。 Value.Call方法允许程序员使用Value调用一个有类型约束的函数;反过来,MakeFunc方法允许程序员使用Value实现一个有类型约束的函数。 下例是一个用MakeFunc创建一个生成不同参数类型的swap函数的代码及其说明。 Example ``` // swap is the implementation passed to MakeFunc. // It must work in terms of reflect.Values so that it is possible // to write code without knowing beforehand what the types // will be. swap := func(in []reflect.Value) []reflect.Value { return []reflect.Value{in[1], in[0]} } // makeSwap expects fptr to be a pointer to a nil function. // It sets that pointer to a new function created with MakeFunc. // When the function is invoked, reflect turns the arguments // into Values, calls swap, and then turns swap's result slice // into the values returned by the new function. makeSwap := func(fptr interface{}) { // fptr is a pointer to a function. // Obtain the function value itself (likely nil) as a reflect.Value // so that we can query its type and then set the value. fn := reflect.ValueOf(fptr).Elem() // Make a function of the right type. v := reflect.MakeFunc(fn.Type(), swap) // Assign it to the value fn represents. fn.Set(v) } // Make and call a swap function for ints. var intSwap func(int, int) (int, int) makeSwap(&intSwap) fmt.Println(intSwap(0, 1)) // Make and call a swap function for float64s. var floatSwap func(float64, float64) (float64, float64) makeSwap(&floatSwap) fmt.Println(floatSwap(2.72, 3.14)) ``` Output: ``` 1 0 3.14 2.72 ``` ### func [Append](https://github.com/golang/go/blob/master/src/reflect/value.go#L1980 "View Source") ``` func Append(s Value, x ...Value) Value ``` 向切片类型的Value值s中添加一系列值,x等Value值持有的值必须能直接赋值给s持有的切片的元素类型。 ### func [AppendSlice](https://github.com/golang/go/blob/master/src/reflect/value.go#L1991 "View Source") ``` func AppendSlice(s, t Value) Value ``` 类似Append函数,但接受一个切片类型的Value值。将切片t的每一个值添加到s。 ### func (Value) [IsValid](https://github.com/golang/go/blob/master/src/reflect/value.go#L1148 "View Source") ``` func (v Value) IsValid() bool ``` IsValid返回v是否持有一个值。如果v是Value零值会返回假,此时v除了IsValid、String、Kind之外的方法都会导致panic。绝大多数函数和方法都永远不返回Value零值。如果某个函数/方法返回了非法的Value,它的文档必须显式的说明具体情况。 ### func (Value) [IsNil](https://github.com/golang/go/blob/master/src/reflect/value.go#L1123 "View Source") ``` func (v Value) IsNil() bool ``` IsNil报告v持有的值是否为nil。v持有的值的分类必须是通道、函数、接口、映射、指针、切片之一;否则IsNil函数会导致panic。注意IsNil并不总是等价于go语言中值与nil的常规比较。例如:如果v是通过使用某个值为nil的接口调用ValueOf函数创建的,v.IsNil()返回真,但是如果v是Value零值,会panic。 ### func (Value) [Kind](https://github.com/golang/go/blob/master/src/reflect/value.go#L1154 "View Source") ``` func (v Value) Kind() Kind ``` Kind返回v持有的值的分类,如果v是Value零值,返回值为Invalid ### func (Value) [Type](https://github.com/golang/go/blob/master/src/reflect/value.go#L1834 "View Source") ``` func (v Value) Type() Type ``` 返回v持有的值的类型的Type表示。 ### func (Value) [Convert](https://github.com/golang/go/blob/master/src/reflect/value.go#L2355 "View Source") ``` func (v Value) Convert(t Type) Value ``` Convert将v持有的值转换为类型为t的值,并返回该值的Value封装。如果go转换规则不支持这种转换,会panic。 ### func (Value) [Elem](https://github.com/golang/go/blob/master/src/reflect/value.go#L831 "View Source") ``` func (v Value) Elem() Value ``` Elem返回v持有的接口保管的值的Value封装,或者v持有的指针指向的值的Value封装。如果v的Kind不是Interface或Ptr会panic;如果v持有的值为nil,会返回Value零值。 ### func (Value) [Bool](https://github.com/golang/go/blob/master/src/reflect/value.go#L352 "View Source") ``` func (v Value) Bool() bool ``` 返回v持有的布尔值,如果v的Kind不是Bool会panic ### func (Value) [Int](https://github.com/golang/go/blob/master/src/reflect/value.go#L1031 "View Source") ``` func (v Value) Int() int64 ``` 返回v持有的有符号整数(表示为int64),如果v的Kind不是Int、Int8、Int16、Int32、Int64会panic ### func (Value) [OverflowInt](https://github.com/golang/go/blob/master/src/reflect/value.go#L1361 "View Source") ``` func (v Value) OverflowInt(x int64) bool ``` 如果v持有值的类型不能无溢出的表示x,会返回真。如果v的Kind不是Int、Int8、Int16、Int32、Int64会panic ### func (Value) [Uint](https://github.com/golang/go/blob/master/src/reflect/value.go#L1867 "View Source") ``` func (v Value) Uint() uint64 ``` 返回v持有的无符号整数(表示为uint64),如v的Kind不是Uint、Uintptr、Uint8、Uint16、Uint32、Uint64会panic ### func (Value) [OverflowUint](https://github.com/golang/go/blob/master/src/reflect/value.go#L1374 "View Source") ``` func (v Value) OverflowUint(x uint64) bool ``` 如果v持有值的类型不能无溢出的表示x,会返回真。如果v的Kind不是Uint、Uintptr、Uint8、Uint16、Uint32、Uint64会panic ### func (Value) [Float](https://github.com/golang/go/blob/master/src/reflect/value.go#L948 "View Source") ``` func (v Value) Float() float64 ``` 返回v持有的浮点数(表示为float64),如果v的Kind不是Float32、Float64会panic ### func (Value) [OverflowFloat](https://github.com/golang/go/blob/master/src/reflect/value.go#L1341 "View Source") ``` func (v Value) OverflowFloat(x float64) bool ``` 如果v持有值的类型不能无溢出的表示x,会返回真。如果v的Kind不是Float32、Float64会panic ### func (Value) [Complex](https://github.com/golang/go/blob/master/src/reflect/value.go#L812 "View Source") ``` func (v Value) Complex() complex128 ``` 返回v持有的复数(表示为complex64),如果v的Kind不是Complex64、Complex128会panic ### func (Value) [OverflowComplex](https://github.com/golang/go/blob/master/src/reflect/value.go#L1328 "View Source") ``` func (v Value) OverflowComplex(x complex128) bool ``` 如果v持有值的类型不能无溢出的表示x,会返回真。如果v的Kind不是Complex64、Complex128会panic ### func (Value) [Pointer](https://github.com/golang/go/blob/master/src/reflect/value.go#L1399 "View Source") ``` func (v Value) Pointer() uintptr ``` 将v持有的值作为一个指针返回。本方法返回值不是unsafe.Pointer类型,以避免程序员不显式导入unsafe包却得到unsafe.Pointer类型表示的指针。如果v的Kind不是Chan、Func、Map、Ptr、Slice或UnsafePointer会panic。 如果v的Kind是Func,返回值是底层代码的指针,但并不足以用于区分不同的函数;只能保证当且仅当v持有函数类型零值nil时,返回值为0。 如果v的Kind是Slice,返回值是指向切片第一个元素的指针。如果持有的切片为nil,返回值为0;如果持有的切片没有元素但不是nil,返回值不会是0。 ### func (Value) [Bytes](https://github.com/golang/go/blob/master/src/reflect/value.go#L362 "View Source") ``` func (v Value) Bytes() []byte ``` 返回v持有的[]byte类型值。如果v持有的值的类型不是[]byte会panic。 ### func (Value) [String](https://github.com/golang/go/blob/master/src/reflect/value.go#L1800 "View Source") ``` func (v Value) String() string ``` 返回v持有的值的字符串表示。因为go的String方法的惯例,Value的String方法比较特别。和其他获取v持有值的方法不同:v的Kind是String时,返回该字符串;v的Kind不是String时也不会panic而是返回格式为"&lt;T value&gt;"的字符串,其中T是v持有值的类型。 ### func (Value) [InterfaceData](https://github.com/golang/go/blob/master/src/reflect/value.go#L1105 "View Source") ``` func (v Value) InterfaceData() [2]uintptr ``` 返回v持有的接口类型值的数据。如果v的Kind不是Interface会panic ### func (Value) [Slice](https://github.com/golang/go/blob/master/src/reflect/value.go#L1698 "View Source") ``` func (v Value) Slice(i, j int) Value ``` 返回v[i:j](v持有的切片的子切片的Value封装);如果v的Kind不是Array、Slice或String会panic。如果v是一个不可寻址的数组,或者索引出界,也会panic ### func (Value) [Slice3](https://github.com/golang/go/blob/master/src/reflect/value.go#L1752 "View Source") ``` func (v Value) Slice3(i, j, k int) Value ``` 是Slice的3参数版本,返回v[i:j:k] ;如果v的Kind不是Array、Slice或String会panic。如果v是一个不可寻址的数组,或者索引出界,也会panic。 ### func (Value) [Cap](https://github.com/golang/go/blob/master/src/reflect/value.go#L788 "View Source") ``` func (v Value) Cap() int ``` 返回v持有值的容量,如果v的Kind不是Array、Chan、Slice会panic ### func (Value) [Len](https://github.com/golang/go/blob/master/src/reflect/value.go#L1160 "View Source") ``` func (v Value) Len() int ``` 返回v持有值的长度,如果v的Kind不是Array、Chan、Slice、Map、String会panic ### func (Value) [Index](https://github.com/golang/go/blob/master/src/reflect/value.go#L969 "View Source") ``` func (v Value) Index(i int) Value ``` 返回v持有值的第i个元素。如果v的Kind不是Array、Chan、Slice、String,或者i出界,会panic ### func (Value) [MapIndex](https://github.com/golang/go/blob/master/src/reflect/value.go#L1184 "View Source") ``` func (v Value) MapIndex(key Value) Value ``` 返回v持有值里key持有值为键对应的值的Value封装。如果v的Kind不是Map会panic。如果未找到对应值或者v持有值是nil映射,会返回Value零值。key的持有值必须可以直接赋值给v持有值类型的键类型。 ### func (Value) [MapKeys](https://github.com/golang/go/blob/master/src/reflect/value.go#L1229 "View Source") ``` func (v Value) MapKeys() []Value ``` 返回一个包含v持有值中所有键的Value封装的切片,该切片未排序。如果v的Kind不是Map会panic。如果v持有值是nil,返回空切片(非nil)。 ### func (Value) [NumField](https://github.com/golang/go/blob/master/src/reflect/value.go#L1320 "View Source") ``` func (v Value) NumField() int ``` 返回v持有的结构体类型值的字段数,如果v的Kind不是Struct会panic ### func (Value) [Field](https://github.com/golang/go/blob/master/src/reflect/value.go#L866 "View Source") ``` func (v Value) Field(i int) Value ``` 返回结构体的第i个字段(的Value封装)。如果v的Kind不是Struct或i出界会panic ### func (Value) [FieldByIndex](https://github.com/golang/go/blob/master/src/reflect/value.go#L907 "View Source") ``` func (v Value) FieldByIndex(index []int) Value ``` 返回索引序列指定的嵌套字段的Value表示,等价于用索引中的值链式调用本方法,如v的Kind非Struct将会panic ### func (Value) [FieldByName](https://github.com/golang/go/blob/master/src/reflect/value.go#L926 "View Source") ``` func (v Value) FieldByName(name string) Value ``` 返回该类型名为name的字段(的Value封装)(会查找匿名字段及其子字段),如果v的Kind不是Struct会panic;如果未找到会返回Value零值。 ### func (Value) [FieldByNameFunc](https://github.com/golang/go/blob/master/src/reflect/value.go#L938 "View Source") ``` func (v Value) FieldByNameFunc(match func(string) bool) Value ``` 返回该类型第一个字段名满足match的字段(的Value封装)(会查找匿名字段及其子字段),如果v的Kind不是Struct会panic;如果未找到会返回Value零值。 ### func (Value) [Recv](https://github.com/golang/go/blob/master/src/reflect/value.go#L1435 "View Source") ``` func (v Value) Recv() (x Value, ok bool) ``` 方法从v持有的通道接收并返回一个值(的Value封装)。如果v的Kind不是Chan会panic。方法会阻塞直到获取到值。如果返回值x对应于某个发送到v持有的通道的值,ok为真;如果因为通道关闭而返回,x为Value零值而ok为假。 ### func (Value) [TryRecv](https://github.com/golang/go/blob/master/src/reflect/value.go#L1817 "View Source") ``` func (v Value) TryRecv() (x Value, ok bool) ``` TryRecv尝试从v持有的通道接收一个值,但不会阻塞。如果v的Kind不是Chan会panic。如果方法成功接收到一个值,会返回该值(的Value封装)和true;如果不能无阻塞的接收到值,返回Value零值和false;如果因为通道关闭而返回,返回值x是持有通道元素类型的零值的Value和false。 ### func (Value) [Send](https://github.com/golang/go/blob/master/src/reflect/value.go#L1470 "View Source") ``` func (v Value) Send(x Value) ``` 方法向v持有的通道发送x持有的值。如果v的Kind不是Chan,或者x的持有值不能直接赋值给v持有通道的元素类型,会panic。 ### func (Value) [TrySend](https://github.com/golang/go/blob/master/src/reflect/value.go#L1827 "View Source") ``` func (v Value) TrySend(x Value) bool ``` TrySend尝试向v持有的通道发送x持有的值,但不会阻塞。如果v的Kind不是Chan会panic。如果成功发送会返回真,否则返回假。x的持有值必须可以直接赋值给v持有通道的元素类型。 ### func (Value) [Close](https://github.com/golang/go/blob/master/src/reflect/value.go#L804 "View Source") ``` func (v Value) Close() ``` 关闭v持有的通道,如果v的Kind不是Chan会panic ### func (Value) [Call](https://github.com/golang/go/blob/master/src/reflect/value.go#L408 "View Source") ``` func (v Value) Call(in []Value) []Value ``` Call方法使用输入的参数in调用v持有的函数。例如,如果len(in) == 3,v.Call(in)代表调用v(in[0], in[1], in[2])(其中Value值表示其持有值)。如果v的Kind不是Func会panic。它返回函数所有输出结果的Value封装的切片。和go代码一样,每一个输入实参的持有值都必须可以直接赋值给函数对应输入参数的类型。如果v持有值是可变参数函数,Call方法会自行创建一个代表可变参数的切片,将对应可变参数的值都拷贝到里面。 ### func (Value) [CallSlice](https://github.com/golang/go/blob/master/src/reflect/value.go#L421 "View Source") ``` func (v Value) CallSlice(in []Value) []Value ``` CallSlice调用v持有的可变参数函数,会将切片类型的in[len(in)-1](的成员)分配给v的最后的可变参数。例如,如果len(in) == 3,v.Call(in)代表调用v(in[0], in[1], in[2])(其中Value值表示其持有值,可变参数函数的可变参数位置提供一个切片并跟三个点号代表"解切片")。如果v的Kind不是Func或者v的持有值不是可变参数函数,会panic。它返回函数所有输出结果的Value封装的切片。和go代码一样,每一个输入实参的持有值都必须可以直接赋值给函数对应输入参数的类型。 ### func (Value) [NumMethod](https://github.com/golang/go/blob/master/src/reflect/value.go#L1289 "View Source") ``` func (v Value) NumMethod() int ``` 返回v持有值的方法集的方法数目。 ### func (Value) [Method](https://github.com/golang/go/blob/master/src/reflect/value.go#L1272 "View Source") ``` func (v Value) Method(i int) Value ``` 返回v持有值类型的第i个方法的已绑定(到v的持有值的)状态的函数形式的Value封装。返回值调用Call方法时不应包含接收者;返回值持有的函数总是使用v的持有者作为接收者(即第一个参数)。如果i出界,或者v的持有值是接口类型的零值(nil),会panic。 ### func (Value) [MethodByName](https://github.com/golang/go/blob/master/src/reflect/value.go#L1304 "View Source") ``` func (v Value) MethodByName(name string) Value ``` 返回v的名为name的方法的已绑定(到v的持有值的)状态的函数形式的Value封装。返回值调用Call方法时不应包含接收者;返回值持有的函数总是使用v的持有者作为接收者(即第一个参数)。如果未找到该方法,会返回一个Value零值。 ### func (Value) [CanAddr](https://github.com/golang/go/blob/master/src/reflect/value.go#L387 "View Source") ``` func (v Value) CanAddr() bool ``` 返回是否可以获取v持有值的指针。可以获取指针的值被称为可寻址的。如果一个值是切片或可寻址数组的元素、可寻址结构体的字段、或从指针解引用得到的,该值即为可寻址的。 ### func (Value) [Addr](https://github.com/golang/go/blob/master/src/reflect/value.go#L343 "View Source") ``` func (v Value) Addr() Value ``` 函数返回一个持有指向v持有者的指针的Value封装。如果v.CanAddr()返回假,调用本方法会panic。Addr一般用于获取结构体字段的指针或者切片的元素(的Value封装)以便调用需要指针类型接收者的方法。 ### func (Value) [UnsafeAddr](https://github.com/golang/go/blob/master/src/reflect/value.go#L1897 "View Source") ``` func (v Value) UnsafeAddr() uintptr ``` 返回指向v持有数据的地址的指针(表示为uintptr)以用作高级用途,如果v不可寻址会panic。 ### func (Value) [CanInterface](https://github.com/golang/go/blob/master/src/reflect/value.go#L1057 "View Source") ``` func (v Value) CanInterface() bool ``` 如果CanInterface返回真,v可以不导致panic的调用Interface方法。 ### func (Value) [Interface](https://github.com/golang/go/blob/master/src/reflect/value.go#L1069 "View Source") ``` func (v Value) Interface() (i interface{}) ``` 本方法返回v当前持有的值(表示为/保管在interface{}类型),等价于: ``` var i interface{} = (v's underlying value) ``` 如果v是通过访问非导出结构体字段获取的,会导致panic。 ### func (Value) [CanSet](https://github.com/golang/go/blob/master/src/reflect/value.go#L396 "View Source") ``` func (v Value) CanSet() bool ``` 如果v持有的值可以被修改,CanSet就会返回真。只有一个Value持有值可以被寻址同时又不是来自非导出字段时,它才可以被修改。如果CanSet返回假,调用Set或任何限定类型的设置函数(如SetBool、SetInt64)都会panic。 ### func (Value) [SetBool](https://github.com/golang/go/blob/master/src/reflect/value.go#L1518 "View Source") ``` func (v Value) SetBool(x bool) ``` 设置v的持有值。如果v的Kind不是Bool或者v.CanSet()返回假,会panic。 ### func (Value) [SetInt](https://github.com/golang/go/blob/master/src/reflect/value.go#L1576 "View Source") ``` func (v Value) SetInt(x int64) ``` 设置v的持有值。如果v的Kind不是Int、Int8、Int16、Int32、Int64之一或者v.CanSet()返回假,会panic。 ### func (Value) [SetUint](https://github.com/golang/go/blob/master/src/reflect/value.go#L1659 "View Source") ``` func (v Value) SetUint(x uint64) ``` 设置v的持有值。如果v的Kind不是Uint、Uintptr、Uint8、Uint16、Uint32、Uint64或者v.CanSet()返回假,会panic。 ### func (Value) [SetFloat](https://github.com/golang/go/blob/master/src/reflect/value.go#L1562 "View Source") ``` func (v Value) SetFloat(x float64) ``` 设置v的持有值。如果v的Kind不是Float32、Float64或者v.CanSet()返回假,会panic。 ### func (Value) [SetComplex](https://github.com/golang/go/blob/master/src/reflect/value.go#L1548 "View Source") ``` func (v Value) SetComplex(x complex128) ``` 设置v的持有值。如果v的Kind不是Complex64、Complex128或者v.CanSet()返回假,会panic。 ### func (Value) [SetBytes](https://github.com/golang/go/blob/master/src/reflect/value.go#L1526 "View Source") ``` func (v Value) SetBytes(x []byte) ``` 设置v的持有值。如果v持有值不是[]byte类型或者v.CanSet()返回假,会panic。 ### func (Value) [SetString](https://github.com/golang/go/blob/master/src/reflect/value.go#L1689 "View Source") ``` func (v Value) SetString(x string) ``` 设置v的持有值。如果v的Kind不是String或者v.CanSet()返回假,会panic。 ### func (Value) [SetPointer](https://github.com/golang/go/blob/master/src/reflect/value.go#L1681 "View Source") ``` func (v Value) SetPointer(x unsafe.Pointer) ``` 设置v的持有值。如果v的Kind不是UnsafePointer或者v.CanSet()返回假,会panic。 ### func (Value) [SetCap](https://github.com/golang/go/blob/master/src/reflect/value.go#L1610 "View Source") ``` func (v Value) SetCap(n int) ``` 设定v持有值的容量。如果v的Kind不是Slice或者n出界(小于长度或超出容量),将导致panic ### func (Value) [SetLen](https://github.com/golang/go/blob/master/src/reflect/value.go#L1597 "View Source") ``` func (v Value) SetLen(n int) ``` 设定v持有值的长度。如果v的Kind不是Slice或者n出界(小于零或超出容量),将导致panic ### func (Value) [SetMapIndex](https://github.com/golang/go/blob/master/src/reflect/value.go#L1626 "View Source") ``` func (v Value) SetMapIndex(key, val Value) ``` 用来给v的映射类型持有值添加/修改键值对,如果val是Value零值,则是删除键值对。如果v的Kind不是Map,或者v的持有值是nil,将会panic。key的持有值必须可以直接赋值给v持有值类型的键类型。val的持有值必须可以直接赋值给v持有值类型的值类型。 ### func (Value) [Set](https://github.com/golang/go/blob/master/src/reflect/value.go#L1499 "View Source") ``` func (v Value) Set(x Value) ``` 将v的持有值修改为x的持有值。如果v.CanSet()返回假,会panic。x的持有值必须能直接赋给v持有值的类型。 ## func [Copy](https://github.com/golang/go/blob/master/src/reflect/value.go#L2005 "View Source") ``` func Copy(dst, src Value) int ``` 将src中的值拷贝到dst,直到src被耗尽或者dst被装满,要求这二者都是slice或array,且元素类型相同。 ## func [DeepEqual](https://github.com/golang/go/blob/master/src/reflect/deepequal.go#L135 "View Source") ``` func DeepEqual(a1, a2 interface{}) bool ``` 用来判断两个值是否深度一致:除了类型相同;在可以时(主要是基本类型)会使用==;但还会比较array、slice的成员,map的键值对,结构体字段进行深入比对。map的键值对,对键只使用==,但值会继续往深层比对。DeepEqual函数可以正确处理循环的类型。函数类型只有都会nil时才相等;空切片不等于nil切片;还会考虑array、slice的长度、map键值对数。 ## Bugs [☞](https://github.com/golang/go/blob/master/src/reflect/type.go#L192 "View Source")FieldByName及相关的函数会将名称相同的结构体字段视为相同的字段,即使它们是来自不同包的非导出字段。这导致如果结构体类型t包含多个名为x的字段的话(被不同的包嵌入)t.FieldByName("x")的行为没有良好的定义。FieldByName可能会返回其中一个名为x的字段,也可能报告说没有这个字段。细节参见golang.org/issue/4876。