【发布时间】:2020-11-23 23:32:17
【问题描述】:
我正在开发我们的一个系统应用程序,特别是在配置文件处理位方面。我们目前有 3 个不同的地方可以存储配置文件,以后可能会对其进行扩展。我正在尝试做的是简化我们需要添加新托管字段的方式。
到目前为止,我的解决方案如下所示:
package main
import (
"reflect"
"strconv"
"strings"
)
type Datastore interface{}
type MyInt struct {
intVal int
}
func NewMyInt(key string, dv int, db *Datastore) *MyInt {
// Do something here to construct MyInt
return &MyInt{intVal: dv}
}
type Config struct {
myInts map[string]*MyInt
// Tag is of form "<key in DB>:<default value>"
Value1 MyInt "value1_key:12345"
Value2 MyInt "value2_key:54321"
}
func NewConfig(db *Datastore) *Config {
c := &Config{
myInts: make(map[string]*MyInt),
}
cType := reflect.TypeOf(c)
for i := 0; i < cType.NumField(); i++ {
f := cType.Field(i)
if f.Name == "myInts" {
continue
}
tag := string(f.Tag)
fields := strings.Split(tag, ":")
switch f.Type.Name() {
case "myInt":
intVal, _ := strconv.Atoi(fields[1])
val := NewMyInt(fields[0], intVal, db)
c.myInts[fields[0]] = val
// How do I set the i'th field to this newly constructed value?
}
}
return c
}
到目前为止,我只是想念这篇文章来完成任务。
【问题讨论】:
-
要了解如何使用
reflect设置结构字段,请参阅peterSO's answer to this question。请注意,尽管使用类型的 name 来决定将其设置为什么类型是……不寻常的,至少;通常你会打开 type 并使用case reflect.TypeOf(...),如示例中所示。如果您有一组“我假设名称 X 是类型 Y”,则无需像该示例的简化版本那样一次遍历一个字段。
标签: go go-reflect