如何使用类似 if-else 的条件在 GO 中动态声明变量的类型?

How to declare the Type of a variable dynamically in GO, using if-else-like conditions?

给定两种类型

type A struct {
    ID         string
    Content    []int
}

type B struct {
    ID         string
    Content    map[string][]int
}

我需要一个函数来告诉我以后根据条件使用哪种类型(目的是正确解组 json 字符串)。我想要一个像

这样的函数
func assign_typed_data(header string) interface{} {
    switch header {
    case "A" :
         d := new(A)
         fmt.Printf('inner type is %T \n', *d)      // inner type is A
         return *d
    case "B" :
         d := new(B)
         fmt.Printf('inner type is %T \n', *d)      // inner type is B
         return *d
    default:
    }
}

在外部代码中我可以调用它并解组 json 如下,但返回值变为“map[string]interface{}”。

header := "A"
data := assign_typed_data(header)
fmt.Printf('outter type is %T \n', data)      // outter type is map[string]interface{}
json.Unmarshal(json_data, &data)

我也尝试在外部代码中直接使用简单的 if-else 语句而不调用函数,如下所示,但也失败了,因为定义的范围是局部的。

if header == "A" {
    data := *new(A)
}else if header == "B" {
    data := *new(B)
}
json.Unmarshal(json_data, &data)

有没有办法在 GO 中实现这个目标?

您必须将指向预期数据类型的指针传递给 json.Unmarshal()。即 *A*B.

然而,assign_typed_data() returns interface{} 并且你获取了它的地址,所以你将通过 *interface{}

assign_typed_data() 更改为 return 指针值 *A*B,并将 data 按原样传递给 json.Unmarshal()已经有一个指针值:

func createValue(header string) interface{} {
    switch header {
    case "A":
        d := new(A)
        fmt.Printf("inner type is %T \n", d) // inner type is *A
        return d
    case "B":
        d := new(B)
        fmt.Printf("inner type is %T \n", d) // inner type is *B
        return d
    default:
        return nil
    }
}

正在测试:

s := `{"ID":"abc","Content":[1,2,3]}`
data := createValue("A")
if err := json.Unmarshal([]byte(s), data); err != nil {
    panic(err)
}
fmt.Printf("outer type is %T \n", data)
fmt.Printf("outer value is %+v \n", data)

s = `{"ID":"abc","Content":{"one":[1,2], "two":[3,4]}}`
data = createValue("B")
if err := json.Unmarshal([]byte(s), data); err != nil {
    panic(err)
}
fmt.Printf("outer type is %T \n", data)
fmt.Printf("outer value is %+v \n", data)

哪些输出(在 Go Playground 上尝试):

inner type is *main.A 
outer type is *main.A 
outer value is &{ID:abc Content:[1 2 3]} 
inner type is *main.B 
outer type is *main.B 
outer value is &{ID:abc Content:map[one:[1 2] two:[3 4]]} 

请检查进一步详细说明问题的相关/可能重复项: