简体   繁体   English

golang中参数中的动态结构

[英]Dynamic struct in parameter in golang

I have to process many files which distinct domain but all of them have line fixed positions我必须处理许多不同域的文件,但它们都具有固定位置

I create structs for domains with tags for start position and end position in line我为域创建了结构体,并带有开始位置和结束位置的标签

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"`
}

And I create a method, which work ok for one table我创建了一个方法,它适用于一张桌子

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 use reflection 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
}

Also getValue use reflection也 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
}

So, is any workaroud to convert the method GetIP0059T01 to a generic method with get the uri and the type, and return an array of interface which can be transformed to the array of the type I pass?那么,将方法 GetIP0059T01 转换为具有获取 uri 和类型的泛型方法,并返回一个可以转换为我传递的类型数组的接口数组,是否有任何解决方法? Basically, I want something like a generic基本上,我想要一个通用的东西

It looks like the only two places where you really need the type is when you allocate it and when you append it to the array.看起来您真正需要该类型的唯一两个地方是分配它时和将它附加到数组时。 So, you can change the function to get two callbacks:因此,您可以更改函数以获取两个回调:

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)


}

And call the function with:并调用函数:

items:=make([]Item,0)
GetStuff(uri, func() interface{} {return new(Item)}, 
func(item interface{}) {items=append(items,*item.(*Item))})

You can do it the same way the Go standard library does it, eg in encoding/json , which is to take in the value to be filled in as a parameter.您可以按照 Go 标准库的方式进行操作,例如在encoding/json ,将要填充的值作为参数。 Your "generic" would be something like:您的“通用”将类似于:

GetValues(bundleURI string, dest interface{}) (error)

Where dest is expected to be a pointer to a slice of whatever type is supposed to be deserialized into, eg:其中dest应该是一个指向任何类型的切片的指针,该切片应该被反序列化,例如:

var v []IP0059T1
err = GetValues(myURI, &v)

Then in GetValues you can use reflect.Type.Elem() to get the type of the slice elements, reflect.New() to create new instances of that type, and reflect.Append() to append them directly into dest .然后在GetValues您可以使用reflect.Type.Elem()获取切片元素的类型,使用reflect.New()创建该类型的新实例,并使用reflect.Append()将它们直接附加到dest This retains type safety while allowing some measure of generic programming.这保留了类型安全性,同时允许某种程度的泛型编程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM