文章目录
- [demo1 数据类型判断](#demo1 数据类型判断)
- [demo2 打印任意类型数据](#demo2 打印任意类型数据)
demo1 数据类型判断
- 使用reflect.TypeOf()方法打印go中数据类型,可参考go官方API文档;
- 使用格式化参数%T也能打印数据类型。
go
package main
import "fmt"
import "reflect"
import "io"
import "os"
func main() {
TypeTest()
}
func TypeTest() {
tInt := reflect.TypeOf(3) // int
tStr := reflect.TypeOf("文字") // string
tBool := reflect.TypeOf(true) // bool
tFloat := reflect.TypeOf(3.14) // float64
tSlice := reflect.TypeOf([]int{1, 2}) // []int
tMap := reflect.TypeOf(map[int]string{}) // map[int]string
var w io.Writer = os.Stdout // *os.File
tW := reflect.TypeOf(w)
fmt.Println(tInt, tStr, tBool, tFloat, tSlice, tMap, tW)
fmt.Printf("%T %T %T %T %T %T %T", 3, "feng", true, 3.14, []int{1, 2}, map[int]string{}, os.Stdout)
}
输出
int string bool float64 []int map[int]string *os.File
int string bool float64 []int map[int]string *os.File
demo2 打印任意类型数据
开始写代码之前,简单了解一些reflect包中的结构体和方法。
1.结构体:reflect.Value(类型+数据指针)
type Value struct {
typ *rtype
ptr unsafe.Pointer
flag
}
type flag uintptr
2.方法:reflect.ValueOf()
入参:接口interface{},也就是任意类型
出参:reflect.Value结构体
func ValueOf(i any) Value {
if i == nil {
return Value{}
}
escapes(i)
return unpackEface(i)
}
3.方法:reflect.Value{}.Interface()
将Value的数据值转为interface{}类型
func (v Value) Interface() (i any) {
return valueInterface(v, true)
}
4.类型:reflect.Kind
实际上Kind是一个uint类型的别名,使用Kind类型定义了go中各种数据类型,枚举如下
(iota变量是0,常量块定义中使用iota,后面的如果没有指定数值,一般就是自增)
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
Pointer
Slice
String
Struct
UnsafePointer
)
-
结构体:reflect.Type(数据类型)
type Type interface {
// 对齐方式
Align() int// 结构体字段的对齐方式 FieldAlign() int // 从方法集合中返回索引为i的方法 Method(int) Method // 通过方法名在方法集合中找方法,返回方法和是否找到的bool类型结果 MethodByName(string) (Method, bool) // 返回方法数量 NumMethod() int // 返回类型的名称,例如 int、string等 Name() string // 返回包路径,例如"encoding/base64" PkgPath() string // 返回类型大小,比如int占8字节 Size() uintptr // 返回最段的类型,例如"base64"而不是"encoding/base64" String() string // 返回类型的数字枚举 Kind() Kind // 返回u类型是否实现了接口 Implements(u Type) bool // 当前类型的值是否可以赋值为u类型 AssignableTo(u Type) bool // 当前类型的值是否可以转换为u类型,就算可转换,依然可能会panic。比如数组大小不匹配时进行转换 ConvertibleTo(u Type) bool // 此类型是否可比较,返回true在比较时也可能panic,因为interface是可比较的,但是interface的子类可能是不可比较的 Comparable() bool Bits() int ChanDir() ChanDir IsVariadic() bool // 返回此类型的元素类型,必须是Array、Chan、Map、Pointer、Slice类型调用,否则会panic Elem() Type // 返回索引为i的结构体类型的字段 Field(i int) StructField // 必须是结构体调用,否则会panic。返回嵌套字段 FieldByIndex(index []int) StructField // 根据名字获取字段,找到返回true FieldByName(name string) (StructField, bool) // 根据条件查找字段 FieldByNameFunc(match func(string) bool) (StructField, bool) // In returns the type of a function type's i'th input parameter. // It panics if the type's Kind is not Func. // It panics if i is not in the range [0, NumIn()). In(i int) Type // Key returns a map type's key type. // It panics if the type's Kind is not Map. Key() Type // Len returns an array type's length. // It panics if the type's Kind is not Array. Len() int // NumField returns a struct type's field count. // It panics if the type's Kind is not Struct. NumField() int // NumIn returns a function type's input parameter count. // It panics if the type's Kind is not Func. NumIn() int // NumOut returns a function type's output parameter count. // It panics if the type's Kind is not Func. NumOut() int // Out returns the type of a function type's i'th output parameter. // It panics if the type's Kind is not Func. // It panics if i is not in the range [0, NumOut()). Out(i int) Type common() *rtype uncommon() *uncommonType
}
了解反射包下的基本数据结构和方法后,下面开始编程
go
package main
import (
"fmt"
"reflect"
"strconv"
)
// 任何类型转打印
func AnyToString(a interface{}) string {
// v是Value类型,属性包含a的实际类型+值
v := reflect.ValueOf(a)
// 判断v的类型
switch v.Kind() {
case reflect.Invalid: // 无效值
return "invalid"
case reflect.String: // 字符串
return v.String()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: // 数字类型
return strconv.FormatInt(v.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: // 无符号数字类型
return strconv.FormatUint(v.Uint(), 10)
case reflect.Bool: // 布尔类型
return strconv.FormatBool(v.Bool())
case reflect.Float64, reflect.Float32: // 浮点数类型
return strconv.FormatFloat(v.Float(), 'f', -1, 64)
case reflect.Ptr: // 指针类型
if v.IsNil() {
return "<nil>"
}
// v.Elem()取出指针指向的数据,类型为reflect.Value
// v.Elem().Interface()将reflect.Value转为interface{}
// AnyToString(v.Elem().Interface()) 递归再次获取字符串
return AnyToString(v.Elem().Interface())
case reflect.Slice, reflect.Array: // 切片和数组类型
s := "["
// 获取数组或者切片的长度
length := v.Len()
for i := 0; i < length; i++ {
// v.Index(i)为获取下标为i的reflect.Value类型数据
// v.Index(i).Interface() 将reflect.Value转为interface{}
// AnyToString(v.Index(i).Interface()) 递归再次获取字符串
s += AnyToString(v.Index(i).Interface())
if i < length-1 {
s += ","
}
}
s += "]"
return s
case reflect.Map: // 字典类型
// 反射获取map的所有key
keys := v.MapKeys()
// 获取map的长度
length := len(keys)
s := "{"
for i := 0; i < length; i++ {
key := keys[i]
// 获取map的value
value := v.MapIndex(key)
s += fmt.Sprintf("%s", AnyToString(key.Interface())) // 拼接key
s += ": "
s += AnyToString(value.Interface()) // 拼接value
if i < length-1 {
s += ", "
}
}
s += "}"
return s
case reflect.Struct: // 结构体类型
s := "{"
count := v.NumField() // 获取结构体的字段数量
for i := 0; i < count; i++ {
// v.Type().Field(i)
s += fmt.Sprintf("%s:%s", v.Type().Field(i).Name, AnyToString(v.Field(i).Interface()))
if i < count-1 {
s += ","
}
}
s += "}"
return s
default: // 其他类型
return fmt.Sprintf("%+v", v)
}
}
func main() {
fmt.Println(AnyToString(1))
fmt.Println(AnyToString("字符串"))
fmt.Println(AnyToString(3.1415926))
fmt.Println(AnyToString(255))
fmt.Println(AnyToString([]int{1, 2, 3}))
fmt.Println(AnyToString(map[string]int{"age": 1}))
account := &Account{
Age: 2,
Name: "jinnian",
}
accountList := []Account{
{1, "wo"},
{0, "c"},
}
fmt.Println(AnyToString(accountList))
fmt.Println(AnyToString(account))
fmt.Println(AnyToString(nil))
fmt.Println(AnyToString(true))
fmt.Println(AnyToString(&accountList))
}
输出
1
字符串
3.1415926
255
[1,2,3]
{age: 1}
[{Age:1,Name:wo},{Age:0,Name:c}]
{Age:2,Name:jinnian}
invalid
true
[{Age:1,Name:wo},{Age:0,Name:c}]
开始学起来吧