Пустой интерфейс interface{

Пустой интерфейс interface{} (или просто пустой интерфейс) — это особый тип в Go, который объявляет ноль методов. Это означает, что любой тип в Go удовлетворяет этому интерфейсу, поскольку для его реализации не требуется реализовывать ни одного метода. Следовательно, переменная типа interface{} может хранить значение абсолютно любого типа: число, строку, структуру, слайс, другую переменную интерфейса или даже сам nil.

Пустой интерфейс часто используется в ситуациях, когда тип данных неизвестен на этапе компиляции, например, при работе с функциями, принимающими аргументы разных типов, или при хранении разнородных значений в коллекциях. Однако следует помнить, что для работы с конкретным значением, хранящимся в пустом интерфейсе, необходимо использовать утверждение типа (type assertion) или переключатель типов (type switch), чтобы получить доступ к его реальному типу и методам.

Синтаксис

govar anyVar interface{}
anyVar = valueOfAnyType

Объявление переменной типа interface{} и присвоение ей значения любого типа.

Пример

Давайте объявим переменную типа interface{} и присвоим ей значения разных типов:

gopackage main

import "fmt"

func main() {
  var anyVar interface{}

  anyVar = 123
  fmt.Println(anyVar)

  anyVar = "hello, world"
  fmt.Println(anyVar)

  anyVar = true
  fmt.Println(anyVar)

  anyVar = []int{1, 2, 3}
  fmt.Println(anyVar)
}

Результат выполнения кода:

go123
"hello, world"
true
[1 2 3]

Как видно из примера, переменная anyVar без проблем хранит значения типа int, string, bool и даже слайс []int.

Пример

Пустой интерфейс часто используется для создания функций, которые могут принимать аргументы любого типа. Например, функция печати с дополнительной информацией:

gopackage main

import "fmt"

func printValue(v interface{}) {
  fmt.Printf("Type: %T, Value: %v\n", v, v)
}

func main() {
  printValue(42)
  printValue("Go")
  printValue(3.14)
  printValue([]string{"a", "b", "c"})
}

Результат выполнения кода:

go"Type: int, Value: 42"
"Type: string, Value: Go"
"Type: float64, Value: 3.14"
"Type: []string, Value: [a b c]"

Функция printValue принимает параметр типа interface{} и с помощью fmt.Printf выводит тип и значение переданного аргумента.

Пример

Пустой интерфейс можно использовать для хранения элементов разных типов в одной коллекции, например, в слайсе:

gopackage main

import "fmt"

func main() {
  mixed := []interface{}{42, "text", 3.14, true, []int{1, 2, 3}}

  for _, val := range mixed {
    fmt.Printf("Value: %v, Type: %T\n", val, val)
  }
}

Результат выполнения кода:

go"Value: 42, Type: int"
"Value: text, Type: string"
"Value: 3.14, Type: float64"
"Value: true, Type: bool"
"Value: [1 2 3], Type: []int"

Слайс mixed может содержать одновременно элементы разных типов благодаря использованию типа элемента interface{}. При итерации по слайсу мы получаем доступ и к значению, и к его динамическому типу.

Смотрите также

  • тип any — псевдоним для interface{}, введенный в Go 1.18,
    который делает код более читаемым
  • операцию утверждение типа,
    которая позволяет извлечь значение конкретного типа из интерфейса
  • конструкцию переключатель типов,
    которая упрощает проверку типа значения, хранящегося в интерфейсе
  • понятие nil-интерфейс,
    которое описывает состояние интерфейсной переменной без присвоенного значения