Instantiating a struct via name using a string in go

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

Instantiating a struct via name using a string in go

问题

我正在尝试创建一个函数,该函数接受一个[]byte和一个interface{}(表示struct),并返回一个作为传递给该函数的struct类型的interface{}

类似这样的代码:

package main

import (
	"encoding/json"
	"fmt"
)

func UnmarshalFromJSONArray(sms []byte, tt string) interface{} {
	var ts interface{}
	err := json.Unmarshal(sms, &ts)
	if err != nil {
		fmt.Println(err)
	}
	return ts
}

然后可以这样调用该方法:

type MyStructType struct {
	Id   int
	Name string
	Desc string
}

mst := "main.MyStructType"
ba := []byte(`{"Id":"3","Name":"Jack","Desc":"the man"}`)

stct := UnmarshalFromJSONArray(ba, mst)

out := stct.(MyStructType)

关键是在解组之前不需要知道MyStructType的字段。我们只需要知道struct的名称,并找到一种实例化它并用与其字段匹配的JSON字节数组数据填充的方法。希望这样做是可能的(在Java中使用反射是微不足道的)。因此,我想通过名称解组一个匿名的struct类型,而不需要知道它有哪些字段。

有什么建议吗?

英文:

I am trying to create a function that takes a []byte and an interface{} (standing for the struct) and returns an interface{} as the struct type passed into the func.

Something like this:

package main

import (

"encoding/json"

)


func UnmarshalFromJSONArray(sms []byte,tt string) (interface{}) {
    var ts = new(tt) 
    err := json.Unmarshal(sms,&ts)
	if(err != nil) {
		fmt.Println(err)
	}
	return sms
}

So that method would run something like this:

// let's say a struct has the following definition:

type MyStructType struct {
    Id int
    Name string
    Desc string
}

// we can some how get its fully qualified class name (this may require reflection?) or pass it into the UnMarshal method direction some how.
mst := "package.MyStructType",

// and then assume a byte array ba that has JSON format for 

ba := []byte(`{"Id":"3","Name":"Jack","Desc":"the man"}`)

stct := UnmarshalFromJSONArray(ba,mst)

MyStructureType out := stct

// leaving "stct" being the unmarshalled byte array which can be used like any other struct of type "MyStructureType"

The key being that I never need to know what the fields of MyStructureType are before unmarshalling. All I need are the name of the struct and some way to instance one and then populate it with JSON byte array data that matches its fields. Hopefully that is possible (it is trivial in java using reflection). So I want to basically unmarshal an anonymous struct type by it's name without needing to know what fields it has.

Any suggestions?

答案1

得分: 4

简短的回答是这是不可能的。Go语言中没有字符串到类型的转换器。你可以创建一个字符串到reflect.Type的映射,但你需要提前知道可能的选项,或者需要提供调用者一种注册类型的方式(可能在init函数中)。

假设你已经找到了将字符串解析为其reflect.Type的方法,你可以简单地调用reflect.New(typ).Interface()来获取需要传递给json.Unmarshal()的指针。

最好的答案是尽量避免尝试这样做。在Go语言中写出符合惯用方式的Java代码实际上是不可能的。如果我对你的问题了解更多,我可以给你一个更符合惯用方式的Go语言解决方案。

英文:

The short answer is that this is impossible. There is no string to type translator in Go. You can make a map of strings to reflect.Type's, but you would need to know the possible options ahead of time or you need to provide the caller with a way to register types (perhaps in init).

Assuming you have found a way to resolve the string to its reflect.Type, you can simply call reflect.New(typ).Interface() to get the pointer you need to pass to json.Unmarshal().

The best answer is to avoid trying this all together. Writing idiomatic Java in Go isn't really possible. If I knew more about your problem, I could give you a more idiomatic Go solution.

huangapple
  • 本文由 发表于 2014年1月4日 11:16:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/20916405.html
匿名

发表评论

匿名网友

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

确定