interface {}的含义是什么?

use*_*973 122 go

我是接口的新手,并试图通过github做SOAP请求

我不明白的意思

Msg interface{}
Run Code Online (Sandbox Code Playgroud)

在这段代码中:

type Envelope struct {
    Body `xml:"soap:"`
}

type Body struct {
    Msg interface{}
}
Run Code Online (Sandbox Code Playgroud)

我观察到相同的语法

fmt.Println
Run Code Online (Sandbox Code Playgroud)

但不明白所取得的成就

interface{}
Run Code Online (Sandbox Code Playgroud)

Von*_*onC 180

您可以参考文章" 如何在Go中使用接口 "(基于" Russ Cox的接口描述 "):

什么界面?

界面是两件事:

  • 这是一套方法,
  • 但它也是一种类型

interface{}类型的空接口是没有方法的接口.

由于没有implements关键字,所有类型都实现至少零方法,并且自动完成满足接口,所有类型都满足空接口.
这意味着如果您编写一个将interface{}值作为参数的函数,则可以为该函数提供任何值.

(这就是Msg你的问题所代表的:任何价值)

func DoSomething(v interface{}) {
   // ...
}
Run Code Online (Sandbox Code Playgroud)

这是令人困惑的地方:

DoSomething函数内部,什么是v类型?

初学者被认为是" v任何类型",但这是错误的.
v不属于任何类型; 它是interface{}类型的.

将值传递给DoSomething函数时,Go运行时将执行类型转换(如果需要),并将值转换为interface{}.
所有值在运行时都只有一种类型,而v一种静态类型是interface{}.

接口值由两个数据字构成:

  • 一个单词用于指向值的基础类型的方法表,
  • 另一个词用于指向该值所持有的实际数据.

附录:这是Russ的文章在界面结构方面相当完整:

type Stringer interface {
    String() string
}
Run Code Online (Sandbox Code Playgroud)

接口值表示为双字对,给出指向存储在接口中的类型的信息的指针和指向相关数据的指针.
将b分配给Stringer类型的接口值会设置接口值的两个字.

http://research.swtch.com/gointer2.png

接口值中的第一个单词指向我称之为接口表或itable(发音为i-table;在运行时源中,C实现名称为Itab).
itable从关于所涉及类型的一些元数据开始,然后成为函数指针的列表.
请注意,itable对应于接口类型,而不是动态类型.
就我们的例子而言,Stringer持有类型Binary 的itable 列出了用于满足Stringer的方法,它只是String:Binary的其他方法(Get)没有出现在itable.

接口值中的第二个字指向实际数据,在这种情况下是一个副本b.
由于var s Stringer = b制作副本的原因相同,分配会复制b而不是指向:如果稍后更改,并且应该具有原始值,而不是新值. 存储在接口中的值可能是任意大的,但只有一个字专用于将值保存在接口结构中,因此赋值在堆上分配一块内存并将指针记录在单字槽中.bvar c uint64 = bbsc

  • "两个数据字"是什么意思?具体来说,"单词"是什么意思? (3认同)
  • @Mingyu我已经完成了解释这两个词(32位点)的答案. (3认同)
  • 感谢@VonC的回复...事实是,当我问问题时,我已经厌倦了下帖...人们大多数时候告诉我,我应该阅读文档...如果我觉得有的话,我会记得你的建议会为它正确写一篇文章......但我真的想不出另一种方式来提问。无论如何,谢谢你,请原谅我的低落。欢迎您查看此内容:/sf/ask/3190411101/?noredirect=1#comment78127620_45577301 以澄清我为什么不这样做不喜欢问。 (3认同)
  • @Mingyu:VonC指的是计算机体系结构意义上的[word](https://en.wikipedia.org/wiki/Word_(computer_architecture)) - 一组定义固定大小数据的位.字大小由您正在使用的处理器体系结构决定. (2认同)
  • @vic 没问题,对于您之前作为提问者的糟糕经历感到抱歉。只是评论不适合问题和答案。 (2认同)

Min*_*nty 32

interface{}意味着您可以放置​​任何类型的值,包括您自己的自定义类型.Go中的所有类型都满足空接口(interface{}是一个空接口).
在您的示例中,Msg字段可以具有任何类型的值.

例:

package main

import (
    "fmt"
)

type Body struct {
    Msg interface{}
}

func main() {
    b := Body{}
    b.Msg = "5"
    fmt.Printf("%#v %T \n", b.Msg, b.Msg) // Output: "5" string
    b.Msg = 5

    fmt.Printf("%#v %T", b.Msg, b.Msg) //Output:  5 int
}
Run Code Online (Sandbox Code Playgroud)

去游乐场

  • 我拥有过的最简单的一个衬垫。以上所有答案都很好,但这个答案很突出。 (2认同)

Den*_*ret 11

它被称为空接口,由所有类型实现,这意味着您可以在该Msg字段中放置任何内容.

示例:

body := Body{3}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:3}

body = Body{"anything"}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:"anything"}

body = Body{body}
fmt.Printf("%#v\n", body) // -> main.Body{Msg:main.Body{Msg:"anything"}}
Run Code Online (Sandbox Code Playgroud)

这是一个类型实现接口的事实的逻辑扩展,只要它具有接口的所有方法.


Ina*_*mus 10

这里已经有了很好的答案.让我自己也加入我想要直观理解它的人:


接口

这是一个有一个方法的接口:

type Runner interface {
    Run()
}
Run Code Online (Sandbox Code Playgroud)

因此任何具有Run()方法的类型都满足Runner接口:

type Program struct {
    /* fields */
}

func (p Program) Run() {
    /* running */
}

func (p Program) Stop() {
    /* stopping */
}
Run Code Online (Sandbox Code Playgroud)
  • 虽然Program类型也有一个Stop方法,但它仍然满足Runner接口,因为所需要的只是让接口的所有方法都满足它.

  • 因此,它有一个Run方法,它满足Runner接口.


空接口

这是一个没有任何方法的命名空接口:

type Empty interface {
    /* it has no methods */
}
Run Code Online (Sandbox Code Playgroud)

所以任何类型都满足这个接口.因为,不需要任何方法来满足此接口.例如:

// Because, Empty interface has no methods, following types satisfy the Empty interface
var a Empty

a = 5
a = 6.5
a = "hello"
Run Code Online (Sandbox Code Playgroud)

但是,上面的程序类型是否满足它?是:

a = Program{} // ok
Run Code Online (Sandbox Code Playgroud)

interface {}等于上面的Empty接口.

var b interface{}

// true: a == b

b = a
b = 9
b = "bye"
Run Code Online (Sandbox Code Playgroud)

如你所见,它并没有什么神秘之处,但它很容易被滥用.尽可能远离它.


https://play.golang.org/p/A-vwTddWJ7G


fab*_*ioM 8

来自Golang规格:

接口类型指定称为其接口的方法集.接口类型的变量可以使用方法集存储任何类型的值,该方法集是接口的任何超集.据说这种类型实现了接口.接口类型的未初始化变量的值为nil.

类型实现包括其方法的任何子集的任何接口,因此可以实现若干不同的接口.例如,所有类型都实现空接口:

接口{}

graps的概念是:

  1. 一切都有类型.您可以定义一个新的类型,我们称之为T.比方说,我们现在的型号T有3种方法:A,B,C.
  2. 为类型指定的方法集称为" 接口类型 ".我们在我们的示例中调用它:T_interface.等于T_interface = (A, B, C)
  3. 您可以通过定义方法的签名来创建"接口类型" .MyInterface = (A, )
  4. 当您指定一个变量类型,"接口类型",可以分配给它仅具有一个接口,你的界面的超类型.这意味着MyInterface包含在内的所有方法都必须包含在内部T_interface

您可以推断出所有类型的所有"接口类型"都是空接口的超集.