Go: How can I "unpack" a struct?

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

Go: How can I "unpack" a struct?

问题

我有一个结构体:

type mystruct struct {
    Foo string
    Bar int
}

我想从这个结构体创建以下形式的SQL插入语句:

m := mystruct{"Hello", 1}
query := "INSERT INTO mytbl (foo, bar) VALUES (?, ?)"
res, err := db.Exec(query, m.Foo, m.Bar)

现在我的问题是:如何根据结构体(或m本身)动态生成最后一行代码?我可以使用reflect获取结构体的字段名,但我不知道如何为db.Exec()调用创建[]interface{}切片。这是我尝试过的代码:(http://play.golang.org/p/GR1Bb61NFH)

package main

import (
    "fmt"
    "reflect"
)

type mystruct struct {
    Foo string
    Bar int
}

func main() {
    m := mystruct{"Foo", 1}
    fmt.Println(readNames(m))
    x := unpackStruct(m)
    fmt.Printf("%#v\n", x)
}

func unpackStruct(a interface{}) []interface{} {

    // 将a转换为m类型

    // 不起作用,来自“反射定律”
    s := reflect.ValueOf(&t).Elem()
    typeOfT := s.Type()
    for i := 0; i < s.NumField(); i++ {
        f := s.Field(i)
        fmt.Printf("%d: %s %s = %v\n", i,
            typeOfT.Field(i).Name, f.Type(), f.Interface())
    }

    // 这是我想要的原则:
    m := mystruct{"Hello", 2}
    var ret []interface{}
    ret = make([]interface{}, s.NumField())
    ret[0] = m.Foo
    ret[1] = m.Bar
    return ret
}

// 运行良好:
func readNames(a interface{}) []string {
    s := reflect.TypeOf(a)
    lenStruct := s.NumField()
    ret := make([]string, lenStruct)

    for i := 0; i < lenStruct; i++ {
        ret[i] = s.Field(i).Name
    }
    return ret
}
英文:

I have a struct:

type mystruct struct {
    Foo string
    Bar int
}

I'd like to create SQL insert statements from the struct which have the following form:

m := mystruct{ &quot;Hello&quot; , 1 }
query := &quot;INSERT INTO mytbl ( foo, bar ) VALUES ( ?,? )&quot;
res,err := db.Exec(query, m.Foo, m.Bar)

Now my question is: how can I make the last line dynamically from the struct (or m) itself? I am able to get the struct names using reflect, but I don't know how to create the []interface{} slice for the db.Exec() call. This is what I have tried: (http://play.golang.org/p/GR1Bb61NFH)

package main

import (
	&quot;fmt&quot;
	&quot;reflect&quot;
)

type mystruct struct {
	Foo string
	Bar int
}

func main() {
	m := mystruct{&quot;Foo&quot;, 1}
	fmt.Println(readNames(m))
	x := unpackStruct(m)
	fmt.Printf(&quot;%#v\n&quot;, x)
}

func unpackStruct(a interface{}) []interface{} {

	// &quot;convert&quot; a to m t

	// doesn&#39;t work, from &#39;laws of reflection&#39;
	s := reflect.ValueOf(&amp;t).Elem()
	typeOfT := s.Type()
	for i := 0; i &lt; s.NumField(); i++ {
		f := s.Field(i)
		fmt.Printf(&quot;%d: %s %s = %v\n&quot;, i,
			typeOfT.Field(i).Name, f.Type(), f.Interface())
	}

	// this is in principle what I want:
	m := mystruct{&quot;Hello&quot;, 2}
	var ret []interface{}
	ret = make([]interface{}, s.NumField())
	ret[0] = m.Foo
	ret[1] = m.Bar
	return ret
}

// works fine:
func readNames(a interface{}) []string {
	s := reflect.TypeOf(a)
	lenStruct := s.NumField()
	ret := make([]string, lenStruct)

	for i := 0; i &lt; lenStruct; i++ {
		ret[i] = s.Field(i).Name
	}
	return ret
}

答案1

得分: 2

如果你的问题是获取字段的值,以下代码片段应该能帮到你:

s := reflect.ValueOf(a)
ret := make([]interface{}, s.NumField())
for i := 0; i < s.NumField(); i++ {
    ret[i] = s.Field(i).Interface()
}
英文:

If getting the values of the fields is your issue, this code snippet should help:

s := reflect.ValueOf(a)
ret := make([]interface{}, s.NumField())
for i := 0; i &lt; s.NumField(); i++ {
    ret[i] = s.Field(i).Interface()
}

答案2

得分: 0

如果创建[]interface{}值是你的问题,使用reflect的切片创建机制应该能很好地解决:

slc := reflect.MakeSlice(InterfaceType, len, cap) // 请参考下面的链接来创建InterfaceType
slc.Index(0).Set(TargetValue)
return slc.Interface()

(这是上述提到的链接)。

修改上述代码以循环遍历结构体中的值而不仅仅是第0个索引应该不会太麻烦。

英文:

If creating the []interface{} value is your problem, using reflect's slice creation mechanisms should work nicely:

slc := reflect.MakeSlice(InterfaceType, len, cap) // See the link below for creating InterfaceType
slc.Index(0).Set(TargetValue)
return slc.Interface()

(Here's the above-mentioned link).

Modifying the above code to loop over the values in the struct instead of just the 0th index shouldn't be too bad.

huangapple
  • 本文由 发表于 2013年9月5日 14:04:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/18628852.html
匿名

发表评论

匿名网友

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

确定