不能使用type interface {}作为赋值类型person:需要类型断言

时间:2014-12-12 04:48:46

标签: go

我尝试将interface{}转换为struct person ...

package main

import (
    "encoding/json"
    "fmt"
)

func FromJson(jsonSrc string) interface{} {
    var obj interface{}
    json.Unmarshal([]byte(jsonSrc), &obj)

    return obj
}

func main() {

    type person struct {
        Name string
        Age  int
    }
    json := `{"Name": "James", "Age": 22}`

    actualInterface := FromJson(json)

    fmt.Println("actualInterface")
    fmt.Println(actualInterface)

    var actual person

    actual = actualInterface // error fires here -------------------------------

    // -------------- type assertion always gives me 'not ok'
    // actual, ok := actualInterface.(person)
    // if ok {

    //  fmt.Println("actual")
    //  fmt.Println(actual)
    // } else {
    //  fmt.Println("not ok")
    //  fmt.Println(actual)
    // }
}

......但是得到了错误:

cannot use type interface {} as type person in assignment: need type assertion

要解决此错误,我尝试使用类型断言actual, ok := actualInterface.(person)但始终获得not ok

Playground link

2 个答案:

答案 0 :(得分:5)

处理此问题的常用方法是将指向输出值的指针传递给解码辅助函数。这可以避免应用程序代码中的类型断言。

package main

import (
    "encoding/json"
    "fmt"
)

func FromJson(jsonSrc string, v interface{}) error {
    return json.Unmarshal([]byte(jsonSrc), v)

}

func main() {
    type person struct {
        Name string
        Age  int
    }
    json := `{"Name": "James", "Age": 22}`

    var p person
    err := FromJson(json, &p)

    fmt.Println(err)
    fmt.Println(p)
}

答案 1 :(得分:3)

您的问题是,您要创建一个空的界面,然后告诉json.Unmarshal解组它。虽然您已经定义了person类型,但json.Unmarshal无法知道您希望JSON的类型是什么。要解决此问题,请将person的定义移至顶层(即将其移出main), and change FromJson`的主体:

func FromJson(jsonSrc string) interface{} {
    var obj person{}
    json.Unmarshal([]byte(jsonSrc), &obj)

    return obj
}

现在,当您返回obj时,返回的interface{}已将person作为其基础类型。您可以在Go Playground上运行此代码。

顺便说一下,你的代码有点不合时宜。除了我的更正之外,我保留了未修改的原始Playground链接,这样它就不会有不必要的混淆。如果您有点好奇,here's a version已经清理得更加惯用(包括我为何做出更改的评论)。