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