Qual o significado da interface {}?

Eu sou novo em interfaces e tentando fazer uma requisição SOAP pelo github

Eu não entendo o significado de

Msg interface{} 

neste código:

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

Eu observei a mesma syntax

 fmt.Println 

mas não entendo o que está sendo alcançado

 interface{} 

Você pode consultar o artigo ” Como usar interfaces no Go ” (baseado na ” descrição das interfaces do Russ Cox “):

O que é uma interface?

Uma interface é duas coisas:

  • é um conjunto de methods
  • mas também é um tipo

O tipo de interface{} , a interface vazia é a interface que não possui methods.

Como não há nenhuma palavra-chave implements, todos os tipos implementam pelo menos zero methods e a satisfação de uma interface é feita automaticamente, todos os tipos satisfazem a interface vazia .
Isso significa que se você escrever uma function que tenha um valor de interface{} como um parâmetro, você poderá fornecer essa function com qualquer valor .

(Isso é o que a Msg representa na sua pergunta: qualquer valor)

 func DoSomething(v interface{}) { // ... } 

Aqui é onde fica confuso:

dentro da function DoSomething , qual é o tipo v ?

Os esquilos iniciantes são levados a acreditar que “ v é de qualquer tipo”, mas isso é errado.
v não é de nenhum tipo; é do tipo interface{} de interface{} .

Ao passar um valor para a function DoSomething , o tempo de execução Ir executará uma conversão de tipo (se necessário) e converterá o valor em um valor interface{} .
Todos os valores têm exatamente um tipo em tempo de execução, e um tipo estático é a interface{} .

Um valor de interface é construído de duas palavras de dados :

  • uma palavra é usada para apontar para uma tabela de methods para o tipo subjacente do valor,
  • e a outra palavra é usada para apontar para os dados reais que estão sendo mantidos por esse valor.

Adendo: Isto é, o artigo de Russ é bastante completo em relação a uma estrutura de interface:

 type Stringer interface { String() string } 

Os valores da interface são representados como um par de duas palavras, fornecendo um ponteiro para informações sobre o tipo armazenado na interface e um ponteiro para os dados associados.
Atribuir b a um valor de interface do tipo Stringer define as duas palavras do valor da interface.

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

A primeira palavra no valor da interface aponta para o que eu chamo de uma tabela de interface ou itable (pronuncia-se i-table; nas fonts runtime, o nome da implementação C é Itab).
O itable começa com alguns metadados sobre os tipos envolvidos e, em seguida, torna-se uma lista de pointers de function.
Observe que o itable corresponde ao tipo de interface, não ao tipo dynamic .
Em termos de nosso exemplo, o itable para Stringer holding type Binary lista os methods usados ​​para satisfazer Stringer, que é apenas String : Os outros methods de Binary ( Get ) não aparecem no itable .

A segunda palavra no valor da interface aponta para os dados reais , neste caso uma cópia de b .
A atribuição var s Stringer = b faz uma cópia de b vez de apontar para b pela mesma razão que var c uint64 = b faz uma cópia: se b depois muda, se supõe que s e c tenham o valor original, não o novo 1.
Valores armazenados em interfaces podem ser arbitrariamente grandes, mas apenas uma palavra é dedicada a manter o valor na estrutura da interface, de modo que a atribuição aloca um pedaço de memory no heap e registra o ponteiro no slot de uma palavra.

interface{} significa que você pode colocar valor de qualquer tipo, incluindo seu próprio tipo personalizado. Todos os tipos em Go satisfazem uma interface vazia ( interface{} é uma interface vazia).
No seu exemplo, o campo Msg pode ter valor de qualquer tipo.

Exemplo:

 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 } 

Vá ao Playground

É chamado de interface vazia e é implementado por todos os tipos, o que significa que você pode colocar qualquer coisa no campo Msg .

Exemplo:

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

Esta é a extensão lógica do fato de que um tipo implementa uma interface assim que tiver todos os methods da interface.

Das especificações de Golang :

Um tipo de interface especifica um conjunto de methods chamado sua interface. Uma variável do tipo de interface pode armazenar um valor de qualquer tipo com um conjunto de methods que seja qualquer superconjunto da interface. Tal tipo é dito para implementar a interface. O valor de uma variável não inicializada do tipo de interface é nulo.

Um tipo implementa qualquer interface que inclua qualquer subconjunto de seus methods e, portanto, pode implementar várias interfaces distintas. Por exemplo, todos os tipos implementam a interface vazia:

interface{}

Os conceitos para os graps são:

  1. Tudo tem um tipo . Você pode definir um novo tipo, vamos chamá-lo de T. Vamos dizer agora que nosso Type T possui 3 methods: A , B , C
  2. O conjunto de methods especificado para um tipo é chamado de ” tipo de interface “. Vamos chamá-lo em nosso exemplo: T_interface. É igual a T_interface = (A, B, C)
  3. Você pode criar um “tipo de interface” definindo a assinatura dos methods. MyInterface = (A, )
  4. Quando você especifica uma variável do tipo , “tipo de interface”, pode designar apenas tipos que tenham uma interface que seja um superconjunto de sua interface. Isso significa que todos os methods contidos no MyInterface devem estar contidos dentro do T_interface

Você pode deduzir que todos os “tipos de interface” de todos os tipos são um superconjunto da interface vazia.

Já existem boas respostas aqui. Deixe-me adicionar o meu próprio também para outras pessoas que querem entendê-lo intuitivamente:


Interface

Aqui está uma interface com um método:

 type Runner interface { Run() } 

Portanto, qualquer tipo que tenha um método Run() satisfaz a interface Runner:

 type Program struct { /* fields */ } func (p Program) Run() { /* running */ } func (p Program) Stop() { /* stopping */ } 
  • Embora o tipo de Programa também tenha um método Stop, ele ainda satisfaz a interface Runner, porque tudo que é necessário é ter todos os methods de uma interface para satisfazê-lo.

  • Então, ele tem um método Run e satisfaz a interface Runner.


Interface Vazia

Aqui está uma interface vazia nomeada sem nenhum método:

 type Empty interface { /* it has no methods */ } 

Então, qualquer tipo satisfaz essa interface. Porque nenhum método é necessário para satisfazer essa interface. Por exemplo:

 // Because, Empty interface has no methods, following types satisfy the Empty interface var a Empty a = 5 a = 6.5 a = "hello" 

Mas, o tipo de programa acima satisfaz isto? Sim:

 a = Program{} // ok 

A interface {} é igual à interface vazia acima.

 var b interface{} // true: a == b b = a b = 9 b = "bye" 

Como você vê, não há nada misterioso sobre isso, mas é muito fácil abusar. Fique longe disso o máximo que puder.


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