[英]Dynamic struct in parameter in golang
我必须处理许多不同域的文件,但它们都具有固定位置
我为域创建了结构体,并带有开始位置和结束位置的标签
type IP0059T1 struct {
TableID string `startpos:"1" endpos:"8"`
EffectiveDateTime string `startpos:"11" endpos:"11"`
}
type IP0059T2 struct {
TableID string `startpos:"1" endpos:"8"`
SequenceNumber string `startpos:"11" endpos:"14"`
}
我创建了一个方法,它适用于一张桌子
func (s *Service) GetIP0059T01(bundleURI string) ([]IP0059T1, error) {
reader := getReader(bundleURI)
var items []IP0059T1
err = patterns.Each(reader, func(e *contract.Entry) error {
line := string(e.Data)
var item = new(IP0059T1)
structName := reflect.TypeOf(item).Name()
structValues := reflect.ValueOf(item).Elem()
for i := 0; i < structValues.NumField(); i++ { // iterates through every struct type field
field := structValues.Field(i) // returns the content of the struct type field
value, _ := getValue(line, structValues.Type().Field(i), structName)
_ = s.SetValue(field, structValues, i, structName, value)
}
items = append(items, *item)
return nil
})
if err != nil {
return nil, err
}
return items, nil
}
setValue 使用反射
func setValue(field reflect.Value, structValues reflect.Value, i int, structName string, value string) error {
if field.Kind() != reflect.String {
return &FieldNotStringError{Field: structValues.Type().Field(i).Name, Struct: structName}
}
field.SetString(value)
return nil
}
也 getValue 使用反射
func getValue(line string, field reflect.StructField, structName string) (string, error) {
startPosition, _ := strconv.Atoi(field.Tag.Get("startpos"))
endPosition, _ := strconv.Atoi(field.Tag.Get("endpos"))
return line[(startPosition - 1):(endPosition)], nil
}
那么,将方法 GetIP0059T01 转换为具有获取 uri 和类型的泛型方法,并返回一个可以转换为我传递的类型数组的接口数组,是否有任何解决方法? 基本上,我想要一个通用的东西
看起来您真正需要该类型的唯一两个地方是分配它时和将它附加到数组时。 因此,您可以更改函数以获取两个回调:
func GetStuff(bundleURI string, newItem func() interface{},collect func(interface{})) error {
// instead of var item = new(IP0059T1)
var item = newItem()
...
// instead of items = append(items, *item)
collect(item)
}
并调用函数:
items:=make([]Item,0)
GetStuff(uri, func() interface{} {return new(Item)},
func(item interface{}) {items=append(items,*item.(*Item))})
您可以按照 Go 标准库的方式进行操作,例如在encoding/json
,将要填充的值作为参数。 您的“通用”将类似于:
GetValues(bundleURI string, dest interface{}) (error)
其中dest
应该是一个指向任何类型的切片的指针,该切片应该被反序列化,例如:
var v []IP0059T1
err = GetValues(myURI, &v)
然后在GetValues
您可以使用reflect.Type.Elem()
获取切片元素的类型,使用reflect.New()
创建该类型的新实例,并使用reflect.Append()
将它们直接附加到dest
。 这保留了类型安全性,同时允许某种程度的泛型编程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.