接口指针作为函数参数

时间:2014-10-14 23:12:16

标签: pointers 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函数更抽象并接受任何结构。我认为最好的方法是接受*interface{},但是在更改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下)?

3 个答案:

答案 0 :(得分:3)

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

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

playground

虽然您可以为Configuration分配interface{},但Configuration值和interface{}值的内存布局不同。由于内存布局不同,因此无法将指向interface{}的指针转换为指向Configuration的指针。 same reasoning applies to a []T and a []interface[}

It's rare to user a pointer to an interface in Go

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

var config *Configuration
config = new(Configuration)

或者您可以使用short variable declaration

config := new(Configuration)

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

答案 1 :(得分:1)

指向接口的指针具有与指向Configuration的指针不同的内存布局。它们不可互换,您不能使用* interface {}来表示任何指针。想象一个像盒子一样的接口值。这个想法是你想要将json函数传递给一个包含指针而不是指向框的指针的框。

如果您想了解界面的基础表示,请参阅http://research.swtch.com/interfaces

答案 2 :(得分:1)

  

接口{}已经是指针吗?

不,一般不是 [1]

  

这里有什么可以让它发挥作用?

考虑以下类型定义:

type Number int

intNumber现在是两种完全不同的类型。您can't使用*int,其中*Number是预期的;即使它们本质上是相同的,甚至是记忆性的。

*Configuration*interface{}的规则相同;即使他们的记忆表达相同(也不是)。

为什么它适用于interface{}呢?因为接口类型很特殊;他们是Go的做多态的方式。任何价值都可以是#34;盒装"在接口值中,如果它实现了所述接口。

[1]在幕后,界面值有时会包含一个指针,但这是一个实现细节,在这里不相关。