What's the meaning of interface{}?
我不熟悉接口,尝试通过Github执行SOAP请求
我不明白
1 | Msg interface{} |
在此代码中:
1 2 3 4 5 6 7 | type Envelope struct { Body `xml:"soap:"` } type Body struct { Msg interface{} } |
号
我在
1 | fmt.Println |
但不知道通过什么
1 | interface{} |
。
您可以参考"如何在Go中使用接口"一文(基于"Russ Cox对接口的描述"):
What is an interface?
An interface is two things:
- it is a set of methods,
- but it is also a type
The
interface{} type, the empty interface is the interface that has no methods.Since there is no implements keyword, all types implement at least zero methods, and satisfying an interface is done automatically, all types satisfy the empty interface.
That means that if you write a function that takes aninterface{} value as a parameter, you can supply that function with any value.
号
(这就是
1 2 3 | func DoSomething(v interface{}) { // ... } |
号
Here’s where it gets confusing:
inside of the
DoSomething function, what isv 's type?Beginner gophers are led to believe that"
v is of any type", but that is wrong.
v is not of any type; it is ofinterface{} type.When passing a value into the
DoSomething function, the Go runtime will perform a type conversion (if necessary), and convert the value to aninterface{} value.
All values have exactly one type at runtime, andv 's one static type isinterface{} .An interface value is constructed of two words of data:
- one word is used to point to a method table for the value’s underlying type,
- and the other word is used to point to the actual data being held by that value.
号
附录:这是Russ关于接口结构的文章非常完整:
1 2 3 | type Stringer interface { String() string } |
Interface values are represented as a two-word pair giving a pointer to information about the type stored in the interface and a pointer to the associated data.
Assigning b to an interface value of type Stringer sets both words of the interface value.
号
。
The first word in the interface value points at what I call an interface table or itable (pronounced i-table; in the runtime sources, the C implementation name is Itab).
The itable begins with some metadata about the types involved and then becomes a list of function pointers.
Note that the itable corresponds to the interface type, not the dynamic type.
In terms of our example, the itable forStringer holding type Binary lists the methods used to satisfy Stringer, which is justString : Binary's other methods (Get ) make no appearance in theitable .The second word in the interface value points at the actual data, in this case a copy of
b .
The assignmentvar s Stringer = b makes a copy ofb rather than point atb for the same reason thatvar c uint64 = b makes a copy: ifb later changes,s andc are supposed to have the original value, not the new one.
Values stored in interfaces might be arbitrarily large, but only one word is dedicated to holding the value in the interface structure, so the assignment allocates a chunk of memory on the heap and records the pointer in the one-word slot.
号
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package main import ( "fmt" ) type Body struct { Msg interface{} } func main() { b := Body{} b.Msg ="5" fmt.Printf("%#v %T ", b.Msg, b.Msg) // Output:"5" string b.Msg = 5 fmt.Printf("%#v %T", b.Msg, b.Msg) //Output: 5 int } |
。
去操场
它被称为空接口,由所有类型实现,这意味着您可以在
例子:
1 2 3 4 5 6 7 8 9 10 11 | body := Body{3} fmt.Printf("%#v ", body) // -> main.Body{Msg:3} body = Body{"anything"} fmt.Printf("%#v ", body) // -> main.Body{Msg:"anything"} body = Body{body} fmt.Printf("%#v ", body) // -> main.Body{Msg:main.Body{Msg:"anything"}} |
这是一个事实的逻辑扩展,即类型一旦拥有接口的所有方法就实现了接口。
这里已经有了很好的答案。让我为那些想要直观理解的人添加我自己的:
接口这里有一个方法接口:
1 2 3 | type Runner interface { Run() } |
因此,具有
1 2 3 4 5 6 7 8 9 10 11 | type Program struct { /* fields */ } func (p Program) Run() { /* running */ } func (p Program) Stop() { /* stopping */ } |
。
尽管程序类型也有一个stop方法,但它仍然满足runner接口,因为需要的只是拥有接口的所有方法来满足它。
所以,它有一个run方法,并且满足runner接口。
- 一切都有一种类型。你可以定义一个新的类型,我们称之为t,现在我们的类型
T 有3种方法:A 、B 、C 。 - 为类型指定的一组方法称为"接口类型"。让我们在示例中调用它:t_接口。等于
T_interface = (A, B, C) 。 - 您可以通过定义方法的签名来创建"接口类型"。江户十一〔七〕号
- 当您指定类型为"interface type"的变量时,您只能为其分配具有接口的类型,该接口是您的接口的超集。这意味着
MyInterface 中包含的所有方法都必须包含在T_interface 中。
小精灵空接口
下面是一个没有任何方法的命名空接口:
1 2 3 | type Empty interface { /* it has no methods */ } |
。
所以任何类型都满足这个接口。因为,不需要任何方法来满足这个接口。例如:
1 2 3 4 5 6 | // Because, Empty interface has no methods, following types satisfy the Empty interface var a Empty a = 5 a = 6.5 a ="hello" |
但是,上面的程序类型满足它吗?对:
1 | a = Program{} // ok |
。
接口等于上面的空接口。
1 2 3 4 5 6 7 | var b interface{} // true: a == b b = a b = 9 b ="bye" |
正如你所看到的,这并没有什么神秘之处,但很容易被滥用。尽量远离它。
网址:https://play.golang.org/p/a-vwtddwj7g
根据Golang规范:
An interface type specifies a method set called its interface. A
variable of interface type can store a value of any type with a method
set that is any superset of the interface. Such a type is said to
implement the interface. The value of an uninitialized variable of
interface type is nil.A type implements any interface comprising any subset of its methods
and may therefore implement several distinct interfaces. For instance,
all types implement the empty interface:interface{}
号
图形的概念是:
您可以推断所有类型的所有"接口类型"都是空接口的超集。