在Go中将结构放入切片的更好方法是什么
我使用func Struct2slicesomestruct Manystrings[]字符串将字符串结构转换为字符串片段。我相信有更好、更快、更简单的方法可以做到这一点,而无需考虑。有吗在Go中将结构放入切片的更好方法是什么,go,struct,slice,Go,Struct,Slice,我使用func Struct2slicesomestruct Manystrings[]字符串将字符串结构转换为字符串片段。我相信有更好、更快、更简单的方法可以做到这一点,而无需考虑。有吗 type Manystrings struct { string1 string string2 string string3 string } func Struct2slice(somestruct Manystrings) []string
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
}
没有
为什么会有?首先,你的函数只有五行代码,它已经很短很简单了。其次,将一个结构转换成一段字符串不是一件正常的事情,至少不足以让它变得比现在更容易。目前,它只比Javascript或PHP稍差一点,对于强类型编译语言来说,这已经是一个相当大的成就。一个人可以直接构造三个字符串的片段-不需要反射 可以为每个结构定义这样的方法。这很简单,尽可能快,也很容易理解 如果您担心像这样的手工编写的方法如何与实际的结构定义不一致,我可能会使用单元测试问题中基于反射的解决方案来检查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"},
... any other test cases
}
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)
}
}
}
回答得很好,非常感谢。对于这个TestStrings,我得到了panic:reflect:call of reflect.Value.NumField on ptr Value[recovered]panic:reflect:call of reflect.Value.NumField on ptr Value耶,对不起-我使用了字符串指针接收器,而您的代码使用了结构。我添加了缺少的反射。间接。
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"},
... any other test cases
}
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)
}
}
}