Pointers 作为函数参数的接口指针

Pointers 作为函数参数的接口指针,pointers,go,Pointers,Go,这很可能源于对go中的接口{}的误解。我有以下代码 type Configuration struct { Username string } func loadJson(jsonStr []byte, x *Configuration}) { json.Unmarshal(jsonStr, x) } func main() { //var config *Configuration config := new(Configuration) file,

这很可能源于对go中的接口{}的误解。我有以下代码

type Configuration struct {
    Username string
}

func loadJson(jsonStr []byte, x *Configuration}) {
    json.Unmarshal(jsonStr, x)
}

func main() {
    //var config *Configuration
    config := new(Configuration)
    file, e := ioutil.ReadFile("config.json")
    loadJson(file, config)
    fmt.Printf("%s\n", config.Username)
}
它将json配置加载到config变量中。我想让loadJson函数更抽象,并接受任何结构。我认为最好的方法是接受一个
*接口{}
,但是在更改loadJson签名时会出现以下错误

 ./issue.go:30: cannot use config (type *Configuration) as type *interface {} in argument to loadJson:
*interface {} is pointer to interface, not interface
相反,加载json应该是这样的

func loadJson(jsonStr []byte, x interface{}}) {
    json.Unmarshal(jsonStr, x)
}
接口{}已经是指针了吗?此外,错误消息对我来说也没有什么意义,配置不是指向接口的指针吗?另外,如果我将
json.Unmarshal(jsonStr,x)
更改为
json.Unmarshal(jsonStr,x)
,它仍然可以正常工作。这里发生了什么事情让它起作用


附带问题但与指针相关,为什么我不能声明一个指针,比如注释掉的行(在main下)

指向接口的指针与指向配置的指针具有不同的内存布局。它们是不可互换的,并且不能使用*接口{}来表示任何指针。将接口值想象成一个方框。其思想是希望向json函数传递一个包含指针的框,而不是指向框的指针


如果要了解接口的底层表示,请参阅。

使用接口{}表示任何类型,包括指针:

func loadJson(jsonStr []byte, x interface{}) {
   json.Unmarshal(jsonStr, x)
}

尽管可以将
配置
分配给
接口{}
,但
配置
值和
接口{}
值的内存布局是不同的。由于内存布局不同,无法将指向
接口{}
的指针转换为指向
配置的指针。这个

关于旁注:您可以使用变量声明和赋值

var config *Configuration
config = new(Configuration)
或者您可以使用:

不能同时使用声明和短声明,因为它声明变量两次

接口{}已经是指针了吗

不,不是一般意义上的[1]

这里发生了什么事情让它起作用

考虑以下类型定义:

type Number int
int
Number
现在是两种完全不同的类型。您使用
*int
,其中需要一个
*Number
;即使它们本质上是相同的,甚至是记忆方面的

规则与
*配置
*接口{}
相同;即使它们的内存表示是相同的(事实并非如此)

那么为什么它适用于
接口{}
?因为接口类型是特殊的;他们是Go的方法。如果接口实现了上述接口,则任何值都可以“装箱”到接口值中

[1] 在后台,接口值有时包含指针,但这是一个实现细节,在这里不相关。

尝试
json.Unmarshal(jsonStr,*x)
type Number int