Что означает интерфейс {}?

Я новичок в интерфейсах и пытаюсь выполнить запрос SOAP github

Я не понимаю смысла

Msg interface{}

в этом коде:

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

type Body struct {
    Msg interface{}
}

Я наблюдал тот же синтаксис в

fmt.Println

но не понимают, что достигается

interface{}

Ответ 1

Вы можете обратиться к статье "Как использовать интерфейсы в Go" (на основе "Описание интерфейсов Russ Coxs" ):

Что такое интерфейс?

Интерфейс - это две вещи:

  • это набор методов,
  • но это также тип

Тип interface{}, пустой интерфейс - это интерфейс, который не имеет методов.

Так как ключевое слово реализует не существует, все типы реализуют по крайней мере нулевые методы, и выполнение интерфейса выполняется автоматически, все типы удовлетворяют пустым интерфейсом.
Это означает, что если вы напишете функцию, которая принимает значение interface{} в качестве параметра, , вы можете предоставить эту функцию с любым значением.

(Это то, что Msg представляет в вашем вопросе: любое значение)

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

Вот где это запутывает:

внутри функции DoSomething, что такое v type?

Начинающие суслики убеждены, что "v имеет любой тип", но это неправильно.
v не имеет никакого типа; имеет тип interface{}.

При передаче значения в функцию DoSomething время выполнения Go будет выполнять преобразование типа (если необходимо) и преобразовать значение в значение interface{} > .
Все значения имеют только один тип во время выполнения, а v один статический тип interface{}.

Значение интерфейса построено из двух слов данных:

  • одно слово используется для указания таблицы методов для значений, лежащих в основе типа,
  • а другое слово используется для указания фактических данных, удерживаемых этим значением.

Приложение: Это была статья Russ довольно полная относительно структуры интерфейса:

type Stringer interface {
    String() string
}

Значения интерфейса представлены в виде пары из двух слов, указав указатель на информацию о типе, хранящемся в интерфейсе, и указатель на связанные данные. Присвоение b значению интерфейса типа Stringer устанавливает оба слова значения интерфейса.

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

Первое слово в значении интерфейса указывает на то, что я называю таблицей интерфейса или itable (произносится как i-table; в источниках времени исполнения имя реализации C - Itab).
Истинный начинается с некоторых метаданных об используемых типах, а затем становится списком указателей на функции.
Обратите внимание, что itable соответствует типу интерфейса, а не динамическому типу.
В терминах нашего примера, пригодный для Stringer типа удержания Binary перечисляет методы, используемые для удовлетворения Stringer, который просто String: двоичные другие методы (Get) не отображаются в itable.

Второе слово в значении интерфейса указывает на фактические данные, в данном случае копию b.
Назначение var s Stringer = b делает копию b вместо точки в b по той же причине, что var c uint64 = b делает копию: если b позже изменяется, s и c должны иметь первоначальное значение, а не новое.
Значения, хранящиеся в интерфейсах, могут быть сколь угодно большими, но только одно слово предназначено для хранения значения в структуре интерфейса, поэтому назначение выделяет кусок памяти в куче и записывает указатель в слот с одним словом.

Ответ 2

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
}

Перейти на площадку

Ответ 3

Он называется пустой интерфейс и реализуется всеми типами, что означает, что вы можете поместить что-либо в поле 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"}}

Это логическое расширение того факта, что тип реализует интерфейс, как только он имеет все методы интерфейса.

Ответ 4

Из Характеристики Голанга:

Тип интерфейса указывает набор методов, называемый его интерфейсом. переменная типа интерфейса может хранить значение любого типа с помощью метода set, который является любым надмножеством интерфейса. Говорят, что такой тип реализовать интерфейс. Значение неинициализированной переменной тип интерфейса равен нулю.

Тип A реализует любой интерфейс, содержащий любое подмножество его методов и поэтому может реализовывать несколько различных интерфейсов. Например, все типы реализуют пустой интерфейс:

интерфейс {}

Понятия для грасс:

  • Все имеет Тип. Вы можете определить новый тип, назовем его T. Скажем, теперь наш тип T имеет 3 метода: A, B, C.
  • Набор методов, заданных для типа, называется " тип интерфейса". Позвольте называть его в нашем примере: T_interface. Является равным T_interface = (A, B, C)
  • Вы можете создать "тип интерфейса", указав методы подпись. MyInterface = (A, )
  • Когда вы указываете переменную типа, тип интерфейса, вы можете назначить ему только типы, у которых есть интерфейс, который является надмножеством вашего интерфейса. Это означает, что все методы, содержащиеся в MyInterface, должны содержаться внутри T_interface

Вы можете вывести, что все "типы интерфейсов" всех типов являются надмножеством пустого интерфейса.