go

go - ¿Cuál es el significado de la interfaz{}?



(5)

Soy nuevo en las interfaces y trato de hacer la solicitud SOAP por github

No entiendo el significado de

Msg interface{}

en este código:

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

He observado la misma sintaxis en

fmt.Println

pero no entiendo lo que se está logrando

interface{}


De las especificaciones de Golang :

Un tipo de interfaz especifica un conjunto de métodos llamado su interfaz. Una variable de tipo de interfaz puede almacenar un valor de cualquier tipo con un conjunto de métodos que sea cualquier superconjunto de la interfaz. Tal tipo se dice que implementa la interfaz. El valor de una variable no inicializada de tipo de interfaz es nulo.

Un tipo implementa cualquier interfaz que comprende cualquier subconjunto de sus métodos y, por lo tanto, puede implementar varias interfaces distintas. Por ejemplo, todos los tipos implementan la interfaz vacía:

interfaz{}

Los conceptos para graps son:

  1. Todo tiene un tipo . Puede definir un nuevo tipo, llamémoslo T. Digamos que ahora nuestro Tipo T tiene 3 métodos: A , B , C
  2. El conjunto de métodos especificado para un tipo se llama " tipo de interfaz ". Vamos a llamarlo en nuestro ejemplo: T_interface. Es igual a T_interface = (A, B, C)
  3. Puede crear un "tipo de interfaz" definiendo la firma de los métodos. MyInterface = (A, )
  4. Cuando especifica una variable de tipo , "tipo de interfaz", puede asignarle solo tipos que tengan una interfaz que sea un superconjunto de su interfaz. Eso significa que todos los métodos contenidos en MyInterface deben estar contenidos dentro de T_interface

Puede deducir que todos los "tipos de interfaz" de todos los tipos son un superconjunto de la interfaz vacía.


Puede consultar el artículo " Cómo usar interfaces en Go " (basado en " la descripción de interfaces de Russ Cox "):

¿Qué es una interfaz?

Una interfaz es dos cosas:

  • es un conjunto de métodos,
  • pero también es un tipo

La interface{} tipo, la interfaz vacía es la interfaz que no tiene métodos.

Como no existe la palabra clave implements, todos los tipos implementan al menos cero métodos, y al satisfacer una interfaz se realiza automáticamente, todos los tipos satisfacen la interfaz vacía .
Esto significa que si escribe una función que toma un valor de interface{} como parámetro, puede suministrar esa función con cualquier valor .

(Eso es lo que Msg representa en su pregunta: cualquier valor)

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

Aquí es donde se vuelve confuso:

dentro de la función DoSomething , ¿cuál es el tipo de v ?

Los topos principiantes son inducidos a creer que " v es de cualquier tipo", pero eso es incorrecto.
v no es de ningún tipo; es de interface{} tipo .

Al pasar un valor a la función DoSomething , el tiempo de ejecución de Go realizará una conversión de tipo (si es necesario) y convertirá el valor a un valor de interface{} .
Todos los valores tienen exactamente un tipo en el tiempo de ejecución, y el único tipo estático de v es la interface{} .

Un valor de interfaz se construye con dos palabras de datos :

  • una palabra se usa para apuntar a una tabla de métodos para el tipo subyacente del valor,
  • y la otra palabra se utiliza para señalar los datos reales que se mantienen por ese valor.

Adición: Este es el artículo de Russ es bastante completo con respecto a una estructura de interfaz:

type Stringer interface { String() string }

Los valores de la interfaz se representan como un par de dos palabras que proporciona un puntero a la información sobre el tipo almacenado en la interfaz y un puntero a los datos asociados.
Asignar b a un valor de interfaz de tipo Stringer establece ambas palabras del valor de la interfaz.

La primera palabra en el valor de la interfaz apunta a lo que llamo una tabla de interfaz o itable (pronunciado i-table; en las fuentes de tiempo de ejecución, el nombre de implementación de C es Itab).
El itable comienza con algunos metadatos sobre los tipos involucrados y luego se convierte en una lista de indicadores de función.
Tenga en cuenta que itable corresponde al tipo de interfaz, no al tipo dinámico .
En términos de nuestro ejemplo, el itable para Stringer holding type Binary enumera los métodos utilizados para satisfacer a Stringer, que es simplemente String : los otros métodos de Binary ( Get ) no aparecen en el itable .

La segunda palabra en el valor de la interfaz apunta a los datos reales , en este caso una copia de b .
La asignación var s Stringer = b hace una copia de b lugar de un punto en b por la misma razón que var c uint64 = b hace una copia: si b cambios posteriores, s y c se supone que tienen el valor original, no el nuevo uno.
Los valores almacenados en las interfaces pueden ser arbitrariamente grandes, pero solo una palabra está dedicada a mantener el valor en la estructura de la interfaz, por lo que la asignación asigna un trozo de memoria en el montón y registra el puntero en el espacio de una palabra.


Se llama interfaz vacía y se implementa por todos los tipos, lo que significa que puede poner cualquier cosa en el campo Msg .

Ejemplo:

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 es la extensión lógica del hecho de que un tipo implementa una interfaz tan pronto como tiene todos los métodos de la interfaz.


Ya hay buenas respuestas aquí. Permítanme agregar el mío también para otros que quieran entenderlo intuitivamente:

Interfaz

Aquí hay una interfaz con un método:

type Runner interface { Run() }

Entonces, cualquier tipo que tenga un método Run() satisface la interfaz Runner:

type Program struct { /* fields */ } func (p Program) Run() { /* running */ } func (p Program) Stop() { /* stopping */ }

  • Aunque el tipo de programa también tiene un método Stop, aún satisface la interfaz Runner porque todo lo que se necesita es tener todos los métodos de una interfaz para satisfacerla.

  • Entonces, tiene un método Run y ​​satisface la interfaz Runner.

Interfaz vacía

Aquí hay una interfaz vacía nombrada sin ningún método:

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

Entonces, cualquier tipo satisface esta interfaz. Porque no se necesita ningún método para satisfacer esta interfaz. Por ejemplo:

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

Pero, ¿el tipo de programa anterior lo satisface? Sí:

a = Program{} // ok

interfaz {} es igual a la interfaz vacía arriba.

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

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


interface{} significa que puede poner valor de cualquier tipo, incluido su propio tipo personalizado. Todos los tipos en Go satisfacen una interfaz vacía (la interface{} es una interfaz vacía).
En su ejemplo, el campo Msg puede tener valor de cualquier tipo.

Ejemplo:

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 }

Ir a la zona de juegos