Align / FieldAlign
函数描述:
- Align:获取变量在内存中的对的字节齐值(通用)
- FieldAlign:获取Struct在内存中的字节对齐值(针对结构体)
关于Go的内存对齐可以参考:https://studygolang.com/articles/19663
使用示例:
func HelloWorld() string {
return "hello world"
}
type St struct {
a int64
b int8
c string
d float64
e func()
}
func main() {
a := St{}
b := int8(10)
c := "hello world"
fmt.Println(reflect.TypeOf(a).Align()) // 8
fmt.Println(reflect.TypeOf(a).FieldAlign()) // 8
fmt.Println(reflect.TypeOf(b).Align()) // 1
fmt.Println(reflect.TypeOf(c).Align()) // 8
fmt.Println(reflect.TypeOf(HelloWorld).Align()) // 8
}
哈哈, 问个问题,以下输出结果是什么?
fmt.Println(unsafe.Sizeof(a))
NumMethod / Method / MethodByName
函数描述:
- NumMethod:返回
可导出
的方法数量 - Method:通过index获取方法信息,此处方法是按
字典顺序
顺序排序,与方法位置先后无关 - MethodByName:通过方法名获取方法信息
使用示例:
type Student struct {
Id int64
Name string
Agent int8
}
func (s Student) Run() {
fmt.Println("run....")
}
func (s Student) Learn() {
fmt.Println("learns....")
}
func(s Student) cray() {
fmt.Println("cry...")
}
func (s *Student) Jump() {
fmt.Println("jump....")
}
func(s *Student) Speak() {
fmt.Println("speak....")
}
func(s *Student) sad () {
fmt.Println("sad...")
}
func main() {
a := Student{}
b := &Student{}
aType := reflect.TypeOf(a)
bType := reflect.TypeOf(b)
fmt.Println(aType.NumMethod())
fmt.Println(bType.NumMethod())
for i :=0; i < aType.NumMethod(); i++ {
name := aType.Method(i).Name
fmt.Println(name)
fmt.Println(aType.MethodByName(name))
}
for i :=0; i < bType.NumMethod(); i++ {
name := bType.Method(i).Name
fmt.Println(name)
fmt.Println(bType.MethodByName(name))
}
if m,ok := aType.MethodByName("sad"); ok {
fmt.Println(m.Name)
}
if m,ok := bType.MethodByName("Speak"); ok {
fmt.Println(m.Name)
}
if m,ok := bType.MethodByName("Speak"); ok {
fmt.Println(m.Name)
}
}
Name / String / Size / PkgPath
函数描述:
- Name:返回类型名称(包内部的名称,不包含包名)
- String:返回类型的字符串表示,此处会使用短包名,如: 会用 base64 代替 encoding/base64,不保证唯一性
- PkgPath:返回变量所在包路径
- Size:返回类型所需存储空间大小,类似于
unsafe.Sizeof
使用示例:
func main() {
c := base64.Encoding{}
cType := reflect.TypeOf(c)
fmt.Println(cType.Name()) // Encoding
fmt.Println(cType.String()) // base64.Encoding
fmt.Println(cType.PkgPath()) // encoding/base64
fmt.Println(cType.Size()) // 328
}
Kind / Implements / AssignableTo / ConvertibleTo / Comparable
函数描述:
- Kind:返回变量类型的分类
- Implements:检测变量是否实现了参数指定的接口,参数必须为interface类型
- AssignableTo:检测变量值是否可以赋值给参数指定的类型
- ConvertibleTo:变量类型值是否可以转换成参数指定的类型的值
- Comparable:变量的类型值是否可比较
Go语言中所有类型如下:
Invalid
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
使用示例:
type Human interface {
Run()
Learn()
Jump()
}
type Student struct {
Id int64
Name string
Agent int8
}
func (s Student) Run() {
fmt.Println("run....")
}
func (s Student) Learn() {
fmt.Println("learns....")
}
func (s Student) cray() {
fmt.Println("cry...")
}
func (s *Student) Jump() {
fmt.Println("jump....")
}
func (s *Student) Speak() {
fmt.Println("speak....")
}
func (s *Student) sad() {
fmt.Println("sad...")
}
func main() {
a := Student{}
b := &Student{}
var c *Human
aType := reflect.TypeOf(a)
bType := reflect.TypeOf(b)
cType := reflect.TypeOf(c).Elem()
fmt.Println(aType.Kind().String()) // Struct
fmt.Println(bType.Kind().String()) // ptr
fmt.Println(cType.Kind().String()) // interface
fmt.Println(aType.Implements(cType)) // false
fmt.Println(bType.Implements(cType)) // true
fmt.Println(bType.AssignableTo(aType)) // false
fmt.Println(bType.AssignableTo(cType)) // true
fmt.Println(bType.ConvertibleTo(aType)) // false
fmt.Println(bType.ConvertibleTo(cType)) // true
fmt.Println(bType.Comparable()) // true
}
上面提到的方法都是都是和类型无关的,所有类型都可以调用,而下面的方法是和类型相关的,只有部分类型可以调用
Elem
方法描述:方法返回类型所对应的元素的类型
- 对于Map类型,返回字典值的类型。
- 对于指针类型Ptr,它返回指针指向的元素的类型。
- 对于Chan,它返回传递的元素的类型。
- 数组和Slice返回的是它包含的元素的类型。
支持类型:Array, Chan, Map, Ptr, Slice
使用示例:
func main() {
a := int8(8)
b := map[string]int64{}
c := make(chan int32)
fmt.Println(reflect.TypeOf(&a).Elem().Name()) // int8
fmt.Println(reflect.TypeOf(b).Elem().Name()) // int64
fmt.Println(reflect.TypeOf(c).Elem().Name()) // int32
}
Bits
方法描述:返回类型所占位大小
支持的类型:Int*, Uint*, Float*, Complex*
使用示例:
func main() {
a := int8(10)
b := float32(30)
c := float64(30)
aType := reflect.TypeOf(&a)
bType := reflect.TypeOf(&b)
cType := reflect.TypeOf(&c)
fmt.Println(aType.Elem().Bits()) // 8
fmt.Println(bType.Elem().Bits()) // 32
fmt.Println(cType.Elem().Bits()) // 64
fmt.Println(dType.Elem().Bits()) // panic
}
ChanDir
方法描述:返回channel的方向
支持的类型:chan
用法示例:
func main() {
a := make(chan<- int)
b := make(<-chan int)
c := make(chan int)
aType := reflect.TypeOf(a)
bType := reflect.TypeOf(b)
cType := reflect.TypeOf(c)
fmt.Println(aType.ChanDir()) // chan <-
fmt.Println(bType.ChanDir()) // <- chan
fmt.Println(cType.ChanDir()) // chan
}
In / NumIn / Out / NumOut / IsVariadic
方法描述:
- NumIn:返回方法参数个数
- In:返回方法第 i 个参数的类型,i 的范围是 [0, NumIn() - 1]
- NumOut:返回方法返回值个数
- Out:返回方法第 i 个 返回值的类型,i 的范围为 [0, NumOut() - 1]
- IsVariadic:判断方法是否存在可变参数
支持类型:Func
使用示例:
func Hello(a, b, c string, d... int) (string, string, []int) {
rtu := fmt.Sprintf("Hello %s %s %s %d", a, b, c, d)
fmt.Println(rtu)
return a, b + c, d
}
func Hello2(a, b, c string, d []int) (string, string, []int) {
rtu := fmt.Sprintf("Hello %s %s %s %d", a, b, c, d)
fmt.Println(rtu)
return a, b + c, d
}
func HelloWorld() {
fmt.Println("Hello World")
}
func main() {
aType := reflect.TypeOf(Hello)
bType := reflect.TypeOf(HelloWorld)
cType := reflect.TypeOf(Hello2)
fmt.Println(aType.NumIn())
for i := 0; i < aType.NumIn(); i++ {
fmt.Println(aType.In(i))
}
fmt.Println(aType.NumOut())
for i:=0; i< aType.NumOut(); i++ {
fmt.Println(aType.Out(i))
}
fmt.Println(aType.IsVariadic()) // true
fmt.Println(bType.IsVariadic()) // false
fmt.Println(cType.IsVariadic()) // false
}
Key
方法描述:返回Map key 的类型
支持类型:Map
使用示例:
func main() {
a := make(map[string]int)
b := make(map[int32]string)
fmt.Println(reflect.TypeOf(a).Key())
fmt.Println(reflect.TypeOf(b).Key())
}
Field / FieldByIndex / FieldByName / FieldByNameFunc / NumField
方法描述:
- Field:获取第 i 个字段的信息,i范围为[0, NumField-1],匿名字段不会自动展开,只认为是一个字段
- NumField:获取结构体字段总数,匿名字段只认为是一个字段
- FieldByIndex:通过 i 获取第 i 个字段信息,支持对结构体嵌套的查找
- FieldByNameFunc:通过传入match方法,来实现对属性的获取,当有且只匹配一次的时候,才正常返回,支持对匿名字段及其字段查找
- FieldByName:通过属性名对结构体字段进行查找
支持类型:Struct
使用示例:
type A struct {
a int
ab int32
b string
c float64
}
type B struct {
c A
d int
f int8
}
type C struct {
d int
f int8
A
}
func main() {
a := A{}
b := B{}
c := C{}
aType := reflect.TypeOf(a)
bType := reflect.TypeOf(b)
cType := reflect.TypeOf(c)
fmt.Println(aType.NumField())
for i := 0; i < aType.NumField();i++ {
fmt.Println(aType.Field(i))
}
fmt.Println(bType.NumField())
for i := 0; i < bType.NumField();i++ {
fmt.Println(bType.Field(i))
}
fmt.Println(cType.NumField())
for i := 0; i < cType.NumField();i++ {
fmt.Println(cType.Field(i))
}
fmt.Println(aType.FieldByIndex([]int{0})) // {a main int 0 [0] false}
fmt.Println(bType.FieldByIndex([]int{0, 2})) // {b main string 16 [2] false}
fmt.Println(aType.FieldByName("a")) // {a main int 0 [0] false} true
fmt.Println(bType.FieldByName("c.a")) // { <nil> 0 [] false} false
fmt.Println(bType.FieldByNameFunc(func(s string) bool {
return strings.HasPrefix(s, "ab")
})) // { <nil> 0 [] false} false
fmt.Println(cType.FieldByNameFunc(func(s string) bool {
return strings.HasPrefix(s, "ab")
})) // {ab main int32 8 [2 1] false} true
fmt.Println(cType.FieldByNameFunc(func(s string) bool {
return strings.HasPrefix(s, "a")
})) // { <nil> 0 [] false} false
}