我有一个 Set 函数,它在我自己的名为 session 的结构中包装了一个用户对象(或变量)。它将它分配给我的 session 结构的值字段。然后 Set 函数编码此结构并将字符串分配到存储中的某处。
我的问题是我不确定如何实现我的 Get 函数以仅返回存储在值字段中的未编码结构,而不是整个 session 包装器结构。
我做了一个非常简单的 example证明我在说什么。
我无法在 Get 函数的赋值中使用类型断言,因为我事先不知道用户将使用什么类型。
我怀疑可能有一种方法可以使用反射来实现这一点?
编辑: 目前提供的两个答案不是我要找的。我不知道用户将使用什么类型,它可能是任何类型,因此通过硬编码他们的类型或试图“猜测”它可能包含的内容来围绕它进行编码是行不通的。
最佳答案
好的,我想我知道你想做什么。我找到了这个答案 Converting map to struct并进行了一些调整以使其适用于您的特定用例。注意:这还没有经过彻底测试,可能有点不稳定,使用风险自负:
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"log"
"reflect"
)
type session struct {
Value interface{}
Flash map[string]string
}
type Person struct {
Name string
Age int
}
func Get(pointer interface{}) {
marshalledString := `{"Value":{"Name":"bob","Age":3},"Flash":null}`
var sess session
d := json.NewDecoder(bytes.NewBuffer([]byte(marshalledString)))
d.UseNumber()
if err := d.Decode(&sess); err != nil {
panic(err)
}
fmt.Printf("%#v", sess)
switch sess.Value.(type) {
case map[string]interface{}:
err := FillStruct(sess.Value.(map[string]interface{}), pointer)
if err != nil {
log.Fatal(err)
}
default:
return // You may want to return an error here...
}
}
func main() {
var personObj Person
Get(&personObj)
// Wanting to see personObj here have Name "bob" and Age 3
fmt.Printf("%#v", personObj)
}
func SetField(obj interface{}, name string, value interface{}) error {
structValue := reflect.ValueOf(obj).Elem()
structFieldValue := structValue.FieldByName(name)
if !structFieldValue.IsValid() {
return fmt.Errorf("No such field: %s in obj", name)
}
if !structFieldValue.CanSet() {
return fmt.Errorf("Cannot set %s field value", name)
}
structFieldType := structFieldValue.Type()
val := reflect.ValueOf(value)
if _, ok := value.(json.Number); ok {
if f, err := value.(json.Number).Int64(); err == nil {
structFieldValue.SetInt(f)
return nil
}
if f, err := value.(json.Number).Float64(); err == nil {
structFieldValue.SetFloat(f)
return nil
}
}
if structFieldType != val.Type() {
return errors.New(fmt.Sprintf("Provided value type [%s] didn't match obj field type [%s]", val.Type().String(), structFieldType.String()))
}
structFieldValue.Set(val)
return nil
}
func FillStruct(m map[string]interface{}, s interface{}) error {
for k, v := range m {
err := SetField(s, k, v)
if err != nil {
return err
}
}
return nil
}
关于json - 将嵌套接口(interface){}解码为用户提供的结构指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41157259/