猿问

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 和类型的泛型方法并返回一个可以转换为我传递的类型的数组的接口数组有什么解决方法吗?基本上,我想要一个通用的东西


萧十郎
浏览 145回答 2
2回答

慕容3067478

看起来您真正需要该类型的唯一两个地方是分配它时以及将其附加到数组时。因此,您可以更改函数以获取两个回调:func GetStuff(bundleURI string, newItem func() interface{},collect func(interface{})) error {&nbsp; &nbsp;// instead of var item = new(IP0059T1)&nbsp; &nbsp;var item = newItem()&nbsp; &nbsp;...&nbsp; &nbsp;// instead of items = append(items, *item)&nbsp; &nbsp;collect(item)}并使用以下方法调用该函数:items:=make([]Item,0)GetStuff(uri, func() interface{} {return new(Item)},&nbsp;func(item interface{}) {items=append(items,*item.(*Item))})

catspeake

你可以像 Go 标准库那样做,例如 in encoding/json,就是把要填写的值作为参数。您的“通用”将类似于:GetValues(bundleURI string, dest interface{}) (error)wheredest应该是指向应该反序列化为任何类型的切片的指针,例如:var v []IP0059T1err = GetValues(myURI, &v)然后,GetValues您可以使用reflect.Type.Elem()获取切片元素的类型,reflect.New()创建该类型的新实例,reflect.Append()并将它们直接附加到dest. 这保留了类型安全,同时允许某种程度的泛型编程。
随时随地看视频慕课网APP

相关分类

Go
我要回答