0

値の配列の配列から構造体の配列を初期化する関数があります。これは私が現在やっている方法です:

type Loadable interface {
  Load([]interface{})
}

type FooList struct {
  Foos []*Foo
}

func (fl *FooList) Load(vals []interface{}) {
  fl.Foos = make([]*Foo, len(vals))
  for i, v := range vals {
    foo := &Foo{}
    foo.Load(v.([]interface{}))
    fl.Foos[i] = foo
  }
}

これは問題なく機能しますが、今度は、Bar と Baz を含む BarList と BazList も初期化する必要があります。コード全体に同じスニペットを振りかける代わりに、次のようになります。

type BarList struct {
  Bars []*Bar
}

func (fl *BarList) Load(vals []interface{}) {
  fl.Bars = make([]*Bar, len(vals))
  for i, v := range vals {
    bar := &Bar{}
    bar.Load(v.([]interface{}))
    fl.Bars[i] = bar
  }
}

このコードをリファクタリングしてより DRY にする正しい方法は何ですか?

4

2 に答える 2

0

リフレクションを使用して思いつくことができる最も簡単なものは、次のようなものです(テストされていません):

import "reflect"

// example_of_type should be an instance of the type, e.g. Foo{}
// returns slice of pointers, e.g. []*Foo
func Load(vals []interface{}, example_of_type interface()) interface{} {
  type := reflect.TypeOf(example_of_type)
  list := reflect.MakeSlice(type.PtrOf().SliceOf(), len(vals), len(vals))
  for i, v := range vals {
    bar := reflect.New(type)
    bar.Interface().(Loadable).Load(v.([]interface{}))
    list.Index(i).Set(bar)
  }
  return list.Interface()
}

次のように使用します。

fl.Foos = Load(vals, Foo{}).([]*Foo)
fl.Bars = Load(vals, Bar{}).([]*Bar)
于 2013-09-01T23:34:20.627 に答える