081-反射(Kind)

Posted --Allen--

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了081-反射(Kind)相关的知识,希望对你有一定的参考价值。

希望你还能记得反射中的 Type 和 Value 这两个类型。Type 是接口类型,Value 是 Struct 类型;Type 是类型描述,而 Value 是具体的值。

这次,我们来看一下 Golang 反射中的另一个重要概念 —— Kind.

1. Kind 定义

A Kind represents the specific kind of type that a Type represents. The zero Kind is not a valid kind.

Kind 的官方定义如上,它描述的是 Type 被归属于哪一类。在 Golang 里,所有 Type 都能归属到下面这些类别:

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
)

举几个例子:

bool // Kind: Bool
int8 // Kind: Int8
type Person struct Name string, Age int8 // Kind: Struct
type Second uint64 // Kind: Uint64
type Reader interface Read(b byte[]) (int, error)  // Kind: Interface

上面这几个类型,总是能被划分到一个类别。

2. 判断 Kind

Type 和 Value 类型都提供了 Kind 方法,来返回其类型的类别。

// Type 中的 Kind 方法
type Type interface 
    ...
    Kind() Kind
    ...


// Value 中的 Kind 方法
type Value Struct 
    ...

func (v Value) Kind() Kind

在上一节我们就已经学会了如果通过变量来获取 Type 和 Value 对象。下面我们利用 Type 或 Value 来获取 Type 的 Kind 类别。

package main

import (
    "fmt"
    "reflect"
)

type Second int
type Person struct 
    Name string
    Age  int


func main() 
    fmt.Println("var s Second") // var s Second
    var s Second = 100
    t := reflect.TypeOf(s)
    fmt.Printf("s.Type.String: %v\\n", t.String()) // s.Type.String: main.Second
    fmt.Printf("s.Type: %v\\n", t) // s.Type: main.Second
    k := t.Kind()
    fmt.Printf("s.Type.kind: %d:%v\\n", k, k) // s.Type.kind: 2:int
    fmt.Println()

    v := reflect.ValueOf(s)
    fmt.Printf("s.Value.String: %v\\n", v.String()) // s.Value.String: <main.Second Value>
    fmt.Printf("s.Value: %v\\n", v) // s.Value: 100
    fmt.Println()

    k = v.Kind()
    fmt.Printf("s.Value.Kind: %d:%v\\n", k, k) // s.Value.Kind: 2:int
    fmt.Println()

    fmt.Println(`var p = Person"allen", 19`) // var p = Person"allen", 19
    var p = Person"allen", 19
    t = reflect.TypeOf(p)
    fmt.Printf("p.Type.String): %v\\n", t.String()) // p.Type.String): main.Person
    fmt.Printf("p.Type: %v\\n", t) // p.Type: main.Person
    k = t.Kind()
    fmt.Printf("p.Type.kind: %d:%v\\n", k, k) // p.Type.kind: 25:struct
    fmt.Println()
    v = reflect.ValueOf(p)
    fmt.Printf("p.Value.String: %v\\n", v.String()) // p.Value.String: <main.Person Value>
    fmt.Printf("p.Value: %v\\n", v) // p.Value: allen 19
    fmt.Println()
    k = v.Kind()

    // 注意变量 p 的 Kind,按照 %d 打印出来的是 25,因为 struct 正好对应 25。
    fmt.Printf("p.Value.Kind: %d:%v\\n", k, k) // s.Value.Kind: 25:struct
    fmt.Println()

3. 总结

  • 掌握 Kind 的定义
  • 知道常见的 Kind 有哪些

知道了判断某个类型的 Kind 以后,一切就好办了,如果是数值类型,我们可以直接使用 %d%f 将其格式化,如果是 Struct 类型,我们可以枚举出这个 Struct 所有的字段名,以及字段名对应的值。

以上是关于081-反射(Kind)的主要内容,如果未能解决你的问题,请参考以下文章

Golang 接口与反射知识要点

go语言学习笔记 — 进阶 — 反射:反射的类型对象(reflect.Type)— 反射类型对象的类型名(Type)和种类(Kind)

GO之反射

go的反射reflect和文件操作

Go反射中的type和kind比较

Go反射中的type和kind比较