Golang运行时动态生成结构体
This commit is contained in:
commit
eab2a7abde
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### Go template
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
.fleet
|
||||||
|
release
|
||||||
|
logs
|
||||||
|
.scannerwork
|
||||||
|
.env
|
||||||
|
__debug*
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2019 Marko Milojevic
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
63
README.md
Normal file
63
README.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# Golang 运行时动态结构体
|
||||||
|
|
||||||
|
主要提供在运行时动态生成结构体的能力, 同时支持合并多个已有结构体,生成一个新的结构体
|
||||||
|
|
||||||
|
主要功能如下:
|
||||||
|
* 运行时动态生成结构体, 更灵活
|
||||||
|
* 运行时继承已有结构体的结构
|
||||||
|
* 运行时合并多个结构体
|
||||||
|
* 向结构体中新增字段
|
||||||
|
* 移除结构体中指定字段
|
||||||
|
* 修改已存在字段的类型以及Tag标签
|
||||||
|
* 读取动态结构体字段的Helper
|
||||||
|
* 动态结构体的值, 解析到一个已定义的结构体中
|
||||||
|
* 懂动态结构体生成slice或者map实例
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"git.zhangdeman.cn/zhangdeman/dynamic-struct"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
instance := NewStruct().
|
||||||
|
AddField("Integer", "", 0, `json:"int"`, false).
|
||||||
|
AddField("Text", "", "", `json:"someText"`, false).
|
||||||
|
AddField("Float", "", 0.0, `json:"double"`, false).
|
||||||
|
AddField("Boolean", "", false, "", false).
|
||||||
|
AddField("Slice", "", []int{}, "", false).
|
||||||
|
AddField("Anonymous", "", "", `json:"-"`, false).
|
||||||
|
Build().
|
||||||
|
New()
|
||||||
|
data := []byte(`
|
||||||
|
{
|
||||||
|
"int": 123,
|
||||||
|
"someText": "example",
|
||||||
|
"double": 123.45,
|
||||||
|
"Boolean": true,
|
||||||
|
"Slice": [1, 2, 3],
|
||||||
|
"Anonymous": "avoid to read"
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, &instance)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err = json.Marshal(instance)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(data))
|
||||||
|
// Out:
|
||||||
|
// {"int":123,"someText":"example","double":123.45,"Boolean":true,"Slice":[1,2,3]}
|
||||||
|
}
|
||||||
|
```
|
185
builder.go
Normal file
185
builder.go
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
package dynamicstruct
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Builder 运行时动态生成结构体的接口约束
|
||||||
|
Builder interface {
|
||||||
|
// AddField 添加结构体字段
|
||||||
|
AddField(name string, pkg string, typ any, tag string, anonymous bool) Builder
|
||||||
|
// RemoveField 移除指定名称的结构体字段
|
||||||
|
RemoveField(name string) Builder
|
||||||
|
// HasField 检测指定名称的结构体字段是否存在
|
||||||
|
HasField(name string) bool
|
||||||
|
// GetField 根据名称获取结构体字段定义
|
||||||
|
GetField(name string) FieldConfig
|
||||||
|
// Build 返回动态定义的结构体.
|
||||||
|
Build() DynamicStruct
|
||||||
|
}
|
||||||
|
|
||||||
|
// FieldConfig 结构体字段的定义.
|
||||||
|
FieldConfig interface {
|
||||||
|
// SetType 设置字段类型.
|
||||||
|
SetType(typ any) FieldConfig
|
||||||
|
// SetTag 设置字段 tag.
|
||||||
|
SetTag(tag string) FieldConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// DynamicStruct contains defined dynamic struct.
|
||||||
|
// This definition can't be changed anymore, once is built.
|
||||||
|
// It provides a method for creating new instances of same defintion.
|
||||||
|
DynamicStruct interface {
|
||||||
|
// New 获取结构体实例, 所有字段值均为对应类型的初始零值
|
||||||
|
New() any
|
||||||
|
|
||||||
|
// NewSliceOfStructs slice实例化
|
||||||
|
NewSliceOfStructs() any
|
||||||
|
|
||||||
|
// NewMapOfStructs map 或者 struct实例化
|
||||||
|
NewMapOfStructs(key any) any
|
||||||
|
}
|
||||||
|
|
||||||
|
builderImpl struct {
|
||||||
|
fields []*fieldConfigImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldConfigImpl struct {
|
||||||
|
name string
|
||||||
|
pkg string
|
||||||
|
typ any
|
||||||
|
tag string
|
||||||
|
anonymous bool
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamicStructImpl struct {
|
||||||
|
definition reflect.Type
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewStruct 获取builder实例
|
||||||
|
func NewStruct() Builder {
|
||||||
|
return &builderImpl{
|
||||||
|
fields: []*fieldConfigImpl{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtendStruct 基于已有结构体, 生成动态结构体(相当于继承指定的结构体属性)
|
||||||
|
func ExtendStruct(value ...any) Builder {
|
||||||
|
return MergeStructs(value...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeStructs 多个结构体合并成一个动态结构体
|
||||||
|
func MergeStructs(values ...any) Builder {
|
||||||
|
builder := NewStruct()
|
||||||
|
|
||||||
|
for _, value := range values {
|
||||||
|
valueOf := reflect.Indirect(reflect.ValueOf(value))
|
||||||
|
typeOf := valueOf.Type()
|
||||||
|
|
||||||
|
for i := 0; i < valueOf.NumField(); i++ {
|
||||||
|
fVal := valueOf.Field(i)
|
||||||
|
fTyp := typeOf.Field(i)
|
||||||
|
builder.(*builderImpl).AddField(fTyp.Name, fTyp.PkgPath, fVal.Interface(), string(fTyp.Tag), fTyp.Anonymous)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddField 添加结构体字段
|
||||||
|
func (b *builderImpl) AddField(name string, pkg string, typ any, tag string, anonymous bool) Builder {
|
||||||
|
if existFieldCfg := b.GetField(name); nil != existFieldCfg {
|
||||||
|
// 说明已存在指定名称字段
|
||||||
|
// 重复添加, 则会议后面的标签以及类型, 覆盖前面的值
|
||||||
|
existFieldCfg.SetTag(tag)
|
||||||
|
existFieldCfg.SetType(typ)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
b.fields = append(b.fields, &fieldConfigImpl{
|
||||||
|
name: name,
|
||||||
|
typ: typ,
|
||||||
|
tag: tag,
|
||||||
|
anonymous: anonymous,
|
||||||
|
pkg: pkg,
|
||||||
|
})
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveField 根据名称移除结构体字段
|
||||||
|
func (b *builderImpl) RemoveField(name string) Builder {
|
||||||
|
newFieldList := make([]*fieldConfigImpl, 0)
|
||||||
|
for i := range b.fields {
|
||||||
|
if b.fields[i].name == name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newFieldList = append(newFieldList, b.fields[i])
|
||||||
|
}
|
||||||
|
b.fields = newFieldList
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasField 是否存在指定字段
|
||||||
|
func (b *builderImpl) HasField(name string) bool {
|
||||||
|
for i := range b.fields {
|
||||||
|
if b.fields[i].name == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetField 根据名称获取字段配置, 不存在, 返回nil
|
||||||
|
func (b *builderImpl) GetField(name string) FieldConfig {
|
||||||
|
for i := range b.fields {
|
||||||
|
if b.fields[i].name == name {
|
||||||
|
return b.fields[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build 构建动态结构体
|
||||||
|
func (b *builderImpl) Build() DynamicStruct {
|
||||||
|
var structFields []reflect.StructField
|
||||||
|
|
||||||
|
for _, field := range b.fields {
|
||||||
|
structFields = append(structFields, reflect.StructField{
|
||||||
|
Name: field.name,
|
||||||
|
PkgPath: field.pkg,
|
||||||
|
Type: reflect.TypeOf(field.typ),
|
||||||
|
Tag: reflect.StructTag(field.tag),
|
||||||
|
Anonymous: field.anonymous,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dynamicStructImpl{
|
||||||
|
definition: reflect.StructOf(structFields),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetType 设置字段类型
|
||||||
|
func (f *fieldConfigImpl) SetType(typ any) FieldConfig {
|
||||||
|
f.typ = typ
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTag 设置字段标签
|
||||||
|
func (f *fieldConfigImpl) SetTag(tag string) FieldConfig {
|
||||||
|
f.tag = tag
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// New 创建动态结构体实例
|
||||||
|
func (ds *dynamicStructImpl) New() any {
|
||||||
|
return reflect.New(ds.definition).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSliceOfStructs 创建动态结构体切片实例
|
||||||
|
func (ds *dynamicStructImpl) NewSliceOfStructs() any {
|
||||||
|
return reflect.New(reflect.SliceOf(ds.definition)).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMapOfStructs 创建动态结构体map实例
|
||||||
|
func (ds *dynamicStructImpl) NewMapOfStructs(key any) any {
|
||||||
|
return reflect.New(reflect.MapOf(reflect.Indirect(reflect.ValueOf(key)).Type(), ds.definition)).Interface()
|
||||||
|
}
|
41
builder_test.go
Normal file
41
builder_test.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Package dynamicstruct ...
|
||||||
|
//
|
||||||
|
// Description : dynamicstruct ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2025-03-19 14:48
|
||||||
|
package dynamicstruct
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_dynamicStructImpl_New(t *testing.T) {
|
||||||
|
instance := NewStruct().
|
||||||
|
AddField("Integer", "", 0, `json:"int"`, false).
|
||||||
|
AddField("Text", "", "", `json:"someText"`, false).
|
||||||
|
AddField("Float", "", 0.0, `json:"double"`, false).
|
||||||
|
AddField("Boolean", "", false, "", false).
|
||||||
|
AddField("Slice", "", []int{}, "", false).
|
||||||
|
AddField("Anonymous", "", "", `json:"-"`, false).
|
||||||
|
Build().
|
||||||
|
New()
|
||||||
|
|
||||||
|
data := []byte(`
|
||||||
|
{
|
||||||
|
"int": 123,
|
||||||
|
"someText": "example",
|
||||||
|
"double": 123.45,
|
||||||
|
"Boolean": true,
|
||||||
|
"Slice": [1, 2, 3],
|
||||||
|
"Anonymous": "avoid to read"
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
err := json.Unmarshal(data, &instance)
|
||||||
|
fmt.Println(err)
|
||||||
|
fmt.Println(reflect.ValueOf(instance).Elem().FieldByName("Integer").Interface())
|
||||||
|
}
|
3
go.mod
Normal file
3
go.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module git.zhangdeman.cn/zhangdeman/dynamic-struct
|
||||||
|
|
||||||
|
go 1.24.1
|
433
reader.go
Normal file
433
reader.go
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
package dynamicstruct
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Reader 通过反射读取结构体信息
|
||||||
|
Reader interface {
|
||||||
|
// HasField 是否存在指定名称的字段
|
||||||
|
HasField(name string) bool
|
||||||
|
// GetField 获取指定字段信息
|
||||||
|
GetField(name string) Field
|
||||||
|
// GetAllFields 获取全部字段
|
||||||
|
GetAllFields() []Field
|
||||||
|
// ToStruct 转结构体
|
||||||
|
ToStruct(value any) error
|
||||||
|
// ToSliceOfReaders 转slice
|
||||||
|
ToSliceOfReaders() []Reader
|
||||||
|
// ToMapReaderOfReaders returns a map of Reader interfaces if value is representation
|
||||||
|
ToMapReaderOfReaders() map[any]Reader
|
||||||
|
// GetValue 获取输入的原始值
|
||||||
|
GetValue() any
|
||||||
|
}
|
||||||
|
|
||||||
|
// Field 对结构体字段的操作
|
||||||
|
Field interface {
|
||||||
|
// Name 返回字段名称
|
||||||
|
Name() string
|
||||||
|
// PointerInt int 指针
|
||||||
|
PointerInt() *int
|
||||||
|
// Int int
|
||||||
|
Int() int
|
||||||
|
// PointerInt8 int8指针
|
||||||
|
PointerInt8() *int8
|
||||||
|
// Int8 int
|
||||||
|
Int8() int8
|
||||||
|
// PointerInt16 int16指针
|
||||||
|
PointerInt16() *int16
|
||||||
|
// Int16 int16
|
||||||
|
Int16() int16
|
||||||
|
// PointerInt32 int32指针
|
||||||
|
PointerInt32() *int32
|
||||||
|
// Int32 int32
|
||||||
|
Int32() int32
|
||||||
|
// PointerInt64 int64指针
|
||||||
|
PointerInt64() *int64
|
||||||
|
// Int64 int64
|
||||||
|
Int64() int64
|
||||||
|
// PointerUint uint指针
|
||||||
|
PointerUint() *uint
|
||||||
|
// Uint uint
|
||||||
|
Uint() uint
|
||||||
|
// PointerUint8 uint8指针
|
||||||
|
PointerUint8() *uint8
|
||||||
|
// Uint8 uint8
|
||||||
|
Uint8() uint8
|
||||||
|
// PointerUint16 uint16指针
|
||||||
|
PointerUint16() *uint16
|
||||||
|
// Uint16 uint16
|
||||||
|
Uint16() uint16
|
||||||
|
// PointerUint32 uint32指针
|
||||||
|
PointerUint32() *uint32
|
||||||
|
// Uint32 uint32
|
||||||
|
Uint32() uint32
|
||||||
|
// PointerUint64 uint64指针
|
||||||
|
PointerUint64() *uint64
|
||||||
|
// Uint64 uint64
|
||||||
|
Uint64() uint64
|
||||||
|
// PointerFloat32 float32指针
|
||||||
|
PointerFloat32() *float32
|
||||||
|
// Float32 float32
|
||||||
|
Float32() float32
|
||||||
|
// PointerFloat64 float64指针
|
||||||
|
PointerFloat64() *float64
|
||||||
|
// Float64 float64
|
||||||
|
Float64() float64
|
||||||
|
// PointerString string指针
|
||||||
|
PointerString() *string
|
||||||
|
// String string
|
||||||
|
String() string
|
||||||
|
// PointerBool bool指针
|
||||||
|
PointerBool() *bool
|
||||||
|
// Bool bool...
|
||||||
|
Bool() bool
|
||||||
|
// PointerTime time指针
|
||||||
|
PointerTime() *time.Time
|
||||||
|
// Time time...
|
||||||
|
Time() time.Time
|
||||||
|
// Any any...
|
||||||
|
Any() any
|
||||||
|
}
|
||||||
|
|
||||||
|
readImpl struct {
|
||||||
|
fields map[string]fieldImpl
|
||||||
|
value any
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldImpl struct {
|
||||||
|
field reflect.StructField
|
||||||
|
value reflect.Value
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewReader reads struct instance and provides instance of
|
||||||
|
// Reader interface to give possibility to read all fields' values.
|
||||||
|
func NewReader(value any) Reader {
|
||||||
|
fields := map[string]fieldImpl{}
|
||||||
|
|
||||||
|
valueOf := reflect.Indirect(reflect.ValueOf(value))
|
||||||
|
typeOf := valueOf.Type()
|
||||||
|
|
||||||
|
if typeOf.Kind() == reflect.Struct {
|
||||||
|
for i := 0; i < valueOf.NumField(); i++ {
|
||||||
|
field := typeOf.Field(i)
|
||||||
|
fields[field.Name] = fieldImpl{
|
||||||
|
field: field,
|
||||||
|
value: valueOf.Field(i),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return readImpl{
|
||||||
|
fields: fields,
|
||||||
|
value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r readImpl) HasField(name string) bool {
|
||||||
|
_, ok := r.fields[name]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r readImpl) GetField(name string) Field {
|
||||||
|
if !r.HasField(name) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return r.fields[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r readImpl) GetAllFields() []Field {
|
||||||
|
var fields []Field
|
||||||
|
|
||||||
|
for _, field := range r.fields {
|
||||||
|
fields = append(fields, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r readImpl) ToStruct(value any) error {
|
||||||
|
valueOf := reflect.ValueOf(value)
|
||||||
|
|
||||||
|
if valueOf.Kind() != reflect.Ptr || valueOf.IsNil() {
|
||||||
|
return errors.New("ToStruct: expected a pointer as an argument")
|
||||||
|
}
|
||||||
|
|
||||||
|
valueOf = valueOf.Elem()
|
||||||
|
typeOf := valueOf.Type()
|
||||||
|
|
||||||
|
if valueOf.Kind() != reflect.Struct {
|
||||||
|
return errors.New("ToStruct: expected a pointer to struct as an argument")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < valueOf.NumField(); i++ {
|
||||||
|
fieldType := typeOf.Field(i)
|
||||||
|
fieldValue := valueOf.Field(i)
|
||||||
|
|
||||||
|
original, ok := r.fields[fieldType.Name]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if fieldValue.CanSet() && r.haveSameTypes(original.value.Type(), fieldValue.Type()) {
|
||||||
|
fieldValue.Set(original.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r readImpl) ToSliceOfReaders() []Reader {
|
||||||
|
valueOf := reflect.Indirect(reflect.ValueOf(r.value))
|
||||||
|
typeOf := valueOf.Type()
|
||||||
|
|
||||||
|
if typeOf.Kind() != reflect.Slice && typeOf.Kind() != reflect.Array {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var readers []Reader
|
||||||
|
|
||||||
|
for i := 0; i < valueOf.Len(); i++ {
|
||||||
|
readers = append(readers, NewReader(valueOf.Index(i).Interface()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return readers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r readImpl) ToMapReaderOfReaders() map[any]Reader {
|
||||||
|
valueOf := reflect.Indirect(reflect.ValueOf(r.value))
|
||||||
|
typeOf := valueOf.Type()
|
||||||
|
|
||||||
|
if typeOf.Kind() != reflect.Map {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
readers := map[any]Reader{}
|
||||||
|
|
||||||
|
for _, keyValue := range valueOf.MapKeys() {
|
||||||
|
readers[keyValue.Interface()] = NewReader(valueOf.MapIndex(keyValue).Interface())
|
||||||
|
}
|
||||||
|
|
||||||
|
return readers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r readImpl) GetValue() any {
|
||||||
|
return r.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r readImpl) haveSameTypes(first reflect.Type, second reflect.Type) bool {
|
||||||
|
if first.Kind() != second.Kind() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch first.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
return r.haveSameTypes(first.Elem(), second.Elem())
|
||||||
|
case reflect.Struct:
|
||||||
|
return first.PkgPath() == second.PkgPath() && first.Name() == second.Name()
|
||||||
|
case reflect.Slice:
|
||||||
|
return r.haveSameTypes(first.Elem(), second.Elem())
|
||||||
|
case reflect.Map:
|
||||||
|
return r.haveSameTypes(first.Elem(), second.Elem()) && r.haveSameTypes(first.Key(), second.Key())
|
||||||
|
default:
|
||||||
|
return first.Kind() == second.Kind()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Name() string {
|
||||||
|
return f.field.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerInt() *int {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Int()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Int() int {
|
||||||
|
return int(reflect.Indirect(f.value).Int())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerInt8() *int8 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Int8()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Int8() int8 {
|
||||||
|
return int8(reflect.Indirect(f.value).Int())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerInt16() *int16 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Int16()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Int16() int16 {
|
||||||
|
return int16(reflect.Indirect(f.value).Int())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerInt32() *int32 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Int32()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Int32() int32 {
|
||||||
|
return int32(reflect.Indirect(f.value).Int())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerInt64() *int64 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Int64()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Int64() int64 {
|
||||||
|
return reflect.Indirect(f.value).Int()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerUint() *uint {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Uint()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Uint() uint {
|
||||||
|
return uint(reflect.Indirect(f.value).Uint())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerUint8() *uint8 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Uint8()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Uint8() uint8 {
|
||||||
|
return uint8(reflect.Indirect(f.value).Uint())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerUint16() *uint16 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Uint16()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Uint16() uint16 {
|
||||||
|
return uint16(reflect.Indirect(f.value).Uint())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerUint32() *uint32 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Uint32()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Uint32() uint32 {
|
||||||
|
return uint32(reflect.Indirect(f.value).Uint())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerUint64() *uint64 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Uint64()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Uint64() uint64 {
|
||||||
|
return reflect.Indirect(f.value).Uint()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerFloat32() *float32 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Float32()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Float32() float32 {
|
||||||
|
return float32(reflect.Indirect(f.value).Float())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerFloat64() *float64 {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Float64()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Float64() float64 {
|
||||||
|
return reflect.Indirect(f.value).Float()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerString() *string {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.String()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) String() string {
|
||||||
|
return reflect.Indirect(f.value).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerBool() *bool {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Bool()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Bool() bool {
|
||||||
|
return reflect.Indirect(f.value).Bool()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) PointerTime() *time.Time {
|
||||||
|
if f.value.IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value := f.Time()
|
||||||
|
return &value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Time() time.Time {
|
||||||
|
value, ok := reflect.Indirect(f.value).Interface().(time.Time)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf(`field "%s" is not instance of time.Time`, f.field.Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f fieldImpl) Any() any {
|
||||||
|
return f.value.Interface()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user