GO中运行时类型的结构的新实例

时间:2015-11-02 01:03:46

标签: reflection go

我正在尝试创建一个结构的新实例,在运行时使用它的类型(reflect.TypeOf)。我在StackOverflow How do you create a new instance of a struct from it's Type at runtime in Go?上关注了这个帖子。这是我的实现(也在http://play.golang.org/p/BtX0d5Ytu8):

package main

import (
    "fmt"
    "reflect"
    "encoding/json"
    "bytes"
)

type UserInfo struct {
    Email    string `json:"email"`
    FullName string `json:"name"`
    ID       string `json:"_id"`
}

func main() {
    fmt.Println("Hello, playground")
    db := DBEngine{}
    db.DB = make(map[string][]byte)

    db.Register(UserInfo{})

    db.Put("142321", UserInfo{"jdoe@acme.com", "John Doe", "142321"})
    ret := db.Get("142321")
    fmt.Println("TypeOf(ret):", reflect.TypeOf(ret))
    fmt.Println("ValueOf(ret):", reflect.ValueOf(ret))
    fmt.Println("Value:", ret)
}

type DBEngine struct {
    Template interface{}
    DB       map[string][]byte
}

func (db *DBEngine) Register(v interface{}) {
    db.Template = v
}

//Set User defined object
func (db *DBEngine) Put(key string, v interface{}) {
    res, _ := json.Marshal(v)
    db.DB[key] = res
}

//Return user defined object
func (db *DBEngine) Get(key string) interface{} {
    decoder := json.NewDecoder(bytes.NewReader(db.DB[key]));
    fmt.Println("Value []byte:", string(db.DB[key]))
    ret := reflect.New(reflect.TypeOf(db.Template)).Elem()
    fmt.Println(reflect.TypeOf(db.Template), ret)
    decoder.Decode(ret)
    return ret.Interface()
}

出于某种原因,我总是得到空结构。我无法设置字段或修改。有人可以提出错误吗?

2 个答案:

答案 0 :(得分:3)

我查看了您的代码。当您使用反射创建一个类型时,您获得了Value类型的值,需要调用Interface()来获取该新生成值的界面

检查代码 http://play.golang.org/p/CHWSV8EG7D

答案 1 :(得分:0)

on run reflect.New(sometype)导致某个类型的reflect.Value指针。如果使用.Elem()将获得为空的reflect.Value的直接值。对于这个main.UserInfo {}。

//Return user defined object
func (db *DBEngine) Get(key string) interface{} {
    decoder := json.NewDecoder(bytes.NewReader(db.DB[key]));
    fmt.Println("Value []byte:", string(db.DB[key]))
    ret := reflect.New(reflect.TypeOf(db.Template)).Elem()//<--wrong
    fmt.Println(reflect.TypeOf(db.Template), ret)
    decoder.Decode(ret)
    return ret.Interface()
}
//print
//Hello, playground
//Value []byte: {"email":"jdoe@acme.com","name":"John Doe","_id":"142321"}
//main.UserInfo {  }
//TypeOf(ret): main.UserInfo
//ValueOf(ret): {  }
//Value: {  }

对于get * sometype值,使用.Interface(),这样你就可以解码了。参见:

//Return user defined object
func (db *DBEngine) Get(key string) interface{} {
    decoder := json.NewDecoder(bytes.NewReader(db.DB[key]));
    fmt.Println("Value []byte:", string(db.DB[key]))
    retValue := reflect.New(reflect.TypeOf(db.Template))
    retInter := retValue.Interface()//<-- 
    fmt.Println(reflect.TypeOf(db.Template), retInter)
    decoder.Decode(retInter)
    return retInter
}

结果:

Hello, playground
Value []byte: {"email":"jdoe@acme.com","name":"John Doe","_id":"142321"}
main.UserInfo &{  }
TypeOf(ret): *main.UserInfo
ValueOf(ret): &{jdoe@acme.com John Doe 142321}
Value: &{jdoe@acme.com John Doe 142321}

在操场上:https://play.golang.org/p/veTUho5D4d