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
}