无法将类型interface {}用作person类型的赋值:需要类型断言

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

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

问题

我尝试将interface{}转换为结构体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 // 错误发生在这里 -------------------------------

	// -------------- 类型断言总是给我 '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链接

英文:

I try to convert interface{} to 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)
	// }
}

... But got error:

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

To solve this error I tried to use type assertion actual, ok := actualInterface.(person) but always got not ok.

Playground link

答案1

得分: 6

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

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)
}
英文:

The usual way to handle this is to pass a pointer to the output value to your decoding helper function. This avoids type assertions in your application code.

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)
}

答案2

得分: 5

你的问题在于你一开始创建了一个空接口,并告诉json.Unmarshal将其解组为该接口。虽然你定义了一个person类型,但json.Unmarshal无法知道你打算将JSON的类型设为什么。要解决这个问题,将person的定义移到顶层(也就是将其移出main函数的主体),并将FromJson函数修改为以下内容:

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

现在,当你返回obj时,返回的interface{}类型的对象的底层类型是person。你可以在Go Playground上运行这段代码。

顺便说一下,你的代码有点不符合惯例。我只对原始的Playground链接进行了修改,除了我所做的更正之外,没有其他不必要的混淆。如果你感兴趣,这里有一个版本进行了清理,更符合惯例(包括对我所做更改的注释)。

英文:

Your problem is that you're creating an empty interface to begin with, and telling json.Unmarshal to unmarshal into it. While you've defined a person type, json.Unmarshal has no way of knowing that that's what you intend the type of the JSON to be. To fix this, move the definition of person to the top level (that is, move it out of the body of main), and change FromJson` to this:

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

Now, when you return obj, the interface{} that's returned has person as its underlying type. You can run this code on the Go Playground.

By the way, your code is a bit un-idiomatic. I left the original Playground link unmodified except for my corrections so that it wouldn't be needlessly confusing. If you're curious, here's a version that's cleaned up to be more idiomatic (including comments on why I made the changes I did).

huangapple
  • 本文由 发表于 2014年12月12日 12:48:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/27437053.html
匿名

发表评论

匿名网友

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

确定