将结构体放入切片的更好方法是什么?

huangapple go评论69阅读模式
英文:

What's the better way to put struct into slice in Go

问题

我有一个名为Struct2slice(somestruct Manystrings) []string的函数,用于将字符串结构体转换为字符串切片。我相信有更好、更快、更简单的方法来做到这一点,而不需要导入reflect包。有吗?

type Manystrings struct {
    string1 string
    string2 string
    string3 string
}

func Struct2slice(somestruct Manystrings) []string {
    v := reflect.ValueOf(somestruct)
    values := make([]string, v.NumField())
    for i := 0; i < v.NumField(); i++ {
        values[i] = v.Field(i).String()
    }
    return values
}
英文:

I have func Struct2slice(somestruct Manystrings) []string to convert struct of strings into slice of strings. I believe there is better, quicker and simpler way to do it, without import reflect . Is there ?

   type Manystrings struct {
    	string1 string
    	string2 string
    	string3 string
    }

func Struct2slice(somestruct Manystrings) []string {

	v := reflect.ValueOf(somestruct)
	values := make([]string, v.NumField())
	for i := 0; i &lt; v.NumField(); i++ {
		values[i] = v.Field(i).String()
	}
	return values
}

答案1

得分: 3

可以直接构建三个字符串的切片,不需要使用reflect

func (ms *ManyStrings) Strings() []string {
    return []string{ms.string1, ms.string2, ms.string3}
}

你可以为每个结构体定义一个类似的方法。这很简单,速度快,易于理解。

如果你担心手动编写的方法可能与实际的结构体定义不一致,我可能会在单元测试中使用你在问题中提到的基于反射的解决方案,来检查Strings()方法是否正确。类似这样:

func toStrings(x interface{}) []string {
  v := reflect.Indirect(reflect.ValueOf(x))
  var r []string
    for i := 0; i < v.NumField(); i++ {
        r = append(r, v.Field(i).String())
    }
    return r
}

func TestStrings(t *testing.T) {
  egs := []interface{Strings()[]string}{
    &ManyStrings{"one", "two", "three"},
    &ManyStrings{},
    &ManyStrings{"a", "", ""},
    &ManyStrings{"", "b", ""},
    &ManyStrings{"", "", "c"},
    ... 其他测试用例
  }
  for _, ex := range egs {
    got, want := ex.Strings(), toStrings(ex)
    if !reflect.DeepEqual(got, want) {
      t.Errorf("%v.Strings() = %v, want %v", ex, got, want)
    }
  }
}
英文:

One can construct a slice of the three strings directly -- there's no need for reflect.

func (ms *ManyStrings) Strings() []string {
    return []string{ms.string1, ms.string2, ms.string3}
}

You can define a method like this for each of the structs you have. That's simple, as fast as it can be, and easy to understand.

If you're concerned about how manually-written methods like this could be inconsistent with the actual struct definitions, I'd probably use the reflection-based solution you have in the question in a unit test, to check that the Strings() methods are correct. Something like this:

func toStrings(x interface{}) []string {
  v := reflect.Indirect(reflect.ValueOf(x))
  var r []string
    for i := 0; i &lt; v.NumField(); i++ {
        r = append(r, v.Field(i).String())
    }
    return r
}

func TestStrings(t *testing.T) {
  egs := []interface{Strings()[]string}{
    &amp;ManyStrings{&quot;one&quot;, &quot;two&quot;, &quot;three&quot;},
    &amp;ManyStrings{},
    &amp;ManyStrings{&quot;a&quot;, &quot;&quot;, &quot;&quot;},
    &amp;ManyStrings{&quot;&quot;, &quot;b&quot;, &quot;&quot;},
    &amp;ManyStrings{&quot;&quot;, &quot;&quot;, &quot;c&quot;},
    ... any other test cases
  }
  for _, ex := range egs {
    got, want := ex.Strings(), toStrings(ex)
    if !reflect.DeepEqual(got, want) {
      t.Errorf(&quot;%v.Strings() = %v, want %v&quot;, ex, got, want)
    }
  }
}

答案2

得分: 1

不会有的。

为什么会有呢?首先,你的函数只有五行代码,已经很短很简单了。其次,将一个结构体转换为字符串切片并不是一件“常规”的事情,至少不足以要求比现在更容易。目前的情况只比JavaScript或PHP稍微不方便一点点,对于一种强类型编译语言来说,这已经是相当了不起的成就了。

英文:

No.

Why would there be? First, your function is only five lines of code, it is already short and simple. Second, converting a struct into a slice of strings is not a "normal" thing to do, at least not enough to mandate making it easier than it already is. As it stands, it is only slightly less convenient than in, say, Javascript or PHP, and that is already quite an achievement for a strongly typed compiled language.

huangapple
  • 本文由 发表于 2017年3月26日 20:31:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/43028719.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定