一、介绍
reflect包主要用来检查interface{}类型的类型type和值value。
我们可以用
reflect.TypeOf() 得到 reflect.Type 反射接口
reflect.ValueOf() 得到 reflect.Value 反射值
在reflect包里,struct里的字段使用 StructField结构体表示
// A StructField describes struct 结构体的 field 字段 .
type StructField struct {
// Name is the field name.
Name string
// PkgPath is the package path that qualifies a lower case (unexported)
PkgPath string
Type Type // field type
Tag StructTag // field tag string
Offset uintptr // offset within struct, in bytes
Index []int // index sequence for Type.FieldByIndex
Anonymous bool // is an embedded field
}
二、reflect.Type
在这里我们以struct举例:打开源码 src/reflect/type.go
type Type interface {
//通用的3个函数
//返回kind,基础类型,Struct,Bool,Int,Int8,Array,Chan,Func,Map...
Kind() Kind
//返回结构体名称
Name() string
//返回包路径
PkgPath() string
//struct相关的3个重要方法,可以看到如果不是struct的话,会报错
// 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 int) StructField
// FieldByName returns the struct field with the given name
// and a boolean indicating if the field was found.
FieldByName(name string) (StructField, bool)
// NumField returns a struct type's field count.
// It panics if the type's Kind is not Struct.
NumField() int
}
本文主要截取了reflect.Type的6个方法以及StructField结构体的field字段
- 通用的方法 Kind(),Name(),PkgPath()
- struct相关方法 NumField(),FieldByName(),Field()
- StructField结构体,用来描述struct结构体的字段field
我们先看一个结构体
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
然后反射获得type类型,打印一下,上面的6个方法:
func TestStructType(t *testing.T) {
p := Person{
Name: "hisheng",
Age: 100,
}
typeP := reflect.TypeOf(p)
t.Log(typeP.Kind()) //struct
t.Log(typeP.Name()) //Person
t.Log(typeP.PkgPath()) //github.com/hisheng/dataStructure/reflect_
t.Log(typeP.NumField()) //2个结构体field字段
t.Log(typeP.Field(0)) //第0个结构体字段,StructField类型 {Name string json:"name" 0 [0] false}
t.Log(typeP.FieldByName("Age")) //获取Age StructField类型 {Age int json:"age" 16 [1] false} true
}
二、reflect.Value
打开源码 src/reflect/value.go 或者用 go doc reflect.value 命令
可以了解到主要由一个reflect.Value结构体以及重要的几个方法组成。
type Value struct {
// typ holds the type of the value represented by a Value.
typ *rtype
// Pointer-valued data or, if flagIndir is set, pointer to data.
// Valid when either flagIndir is set or typ.pointers() is true.
ptr unsafe.Pointer
// flag holds metadata about the value.
flag
}
主要的方法有:
func (v Value) Kind() Kind
func (v Value) NumField() int
func (v Value) Field(i int) Value
func (v Value) FieldByName(name string) Value
我们这里使用一下:
func TestStructValue(t *testing.T) {
p := Person{
Name: "hisheng",
Age: 100,
}
valueP := reflect.ValueOf(p)
t.Log(valueP.Kind()) //struct
t.Log(valueP.NumField()) //2
t.Log(valueP.Field(0)) // 返回reflect.Value 打印 hisheng
t.Log(valueP.FieldByName("Age")) //返回reflect.Value 打印 100
}
三、StructField 结构体字段
package reflect_
import (
"reflect"
"testing"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
password []byte
Address Address `json:"address"`
}
type Address struct {
Country string `json:"country"`
City string `json:"city"`
}
//遍历struct
func TestStructField(t *testing.T) {
p := Person{
Name: "hisheng",
Age: 100,
password: []byte("pwd"),
Address: Address{Country: "china", City: "shanghai"},
}
typeP := reflect.TypeOf(p)
if typeP.Kind() == reflect.Struct {
//遍历struct
for i := 0; i < typeP.NumField(); i++ {
structField := typeP.Field(i)
t.Logf("%s %s %s", structField.Name, structField.Type, structField.Tag)
}
}
}
输出如下:
Name string json:"name"
Age int json:"age"
password []uint8
Address reflect_.Address json:"address"
可以发现,我们打印出了 Person 结构体的 每一个field字段。
四、StructTag 结构体字段tag
Struct Tag是存在于Struct字段下面成员的附加属性,
它的定义永远都是以key-value的形式出现的,多个定义的情况下以空格分割
package reflect_
import (
"reflect"
"testing"
)
type Person struct {
Name string `json:"name,omitempty" xml:"name_x"`
Age int `json:"age"`
}
func TestStructFieldTag(t *testing.T) {
p := Person{Name: "hisheng"}
typeP := reflect.TypeOf(p)
if typeP.Kind() == reflect.Struct {
structField := typeP.Field(0) // 对应Name这个 字段
var structFieldTag reflect.StructTag = structField.Tag
t.Log(structFieldTag) //json:"name,omitempty" xml:"name_x"
t.Log(structFieldTag.Get("json")) //name,omitempty
t.Log(structFieldTag.Get("xml")) //name_x
}
}
好文学习补充:
深度剖析Reflect + 实战案例
Go 每日一库之 reflect
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。