Пустой интерфейс (any)
Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy. Урок 28 из 107.
Пустой интерфейс — это interface с нулём методов. Поскольку каждый тип в Go имеет как минимум ноль методов, любой тип автоматически удовлетворяет пустому interface. Благодаря этому он способен хранить значения любого типа.
var anything interface{}
anything = 42
anything = "hello"
anything = true
anything = []int{1, 2, 3}Начиная с Go 1.18, ключевое слово any было введено как псевдоним для interface{}. Они полностью взаимозаменяемы, но any легче читать.
var value any = "Go is awesome"Пустой interface полезен, когда вам нужно обрабатывать значения неизвестных типов или типов, которые могут изменяться. Такие функции, как fmt.Println, используют его, чтобы принимать аргументы любого типа:
func PrintAnything(v any) {
fmt.Println("Value:", v)
}
func main() {
PrintAnything(100)
PrintAnything("text")
PrintAnything(3.14)
}Однако здесь есть компромисс. Когда значение хранится в пустом interface, вы теряете доступ к информации о его конкретном типе.
Нельзя напрямую вызывать methods или обращаться к field, не извлекая сначала базовый type. В следующих уроках будет рассмотрено, как получить конкретный type из пустого interface с помощью утверждений типа и переключателей типов.
Задание
ЛегкоДавайте создадим гибкий контейнер для хранения, который может содержать значения любого типа, используя пустой interface. Вы создадите простую коробку, демонстрирующую, как any позволяет хранить разные типы в одной и той же структуре.
Вы организуете свой код в двух файлах:
box.go: Define структуруBoxс одним полемContentтипаany. Create конструкторNewBox, который accepts значение любого типа и returns pointer на Box, содержащий это значение. Add methodDescribe, который returns string с описанием того, что хранится в коробке.main.go: Read разные значения из ввода, создайте коробки, содержащие integer, string и boolean, затем выведите описание каждой коробки, чтобы показать, как один и тот же тип Box может содержать совершенно разные значения.
Будут предоставлены следующие входные данные:
- Строка 1: значение integer
- Строка 2: значение string
- Строка 3: значение boolean (
trueилиfalse)
Ваш method Describe должен возвращать string в следующем формате:
Box contains: [value]Например, если заданы 42, hello и true, результатом должно быть:
Box contains: 42
Box contains: hello
Box contains: trueГлавная идея заключается в том, что ваша единственная структура Box может хранить integer, string или boolean: всё благодаря тому, что тип any accepts значения любого типа. Каждая коробка хранит что-то своё, но все они имеют один и тот же тип Box.
Попробуйте сами
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Прочитать целочисленное значение
line1, _ := reader.ReadString('\n')
intVal, _ := strconv.Atoi(strings.TrimSpace(line1))
// Прочитать строковое значение
line2, _ := reader.ReadString('\n')
strVal := strings.TrimSpace(line2)
// Прочитать логическое значение
line3, _ := reader.ReadString('\n')
boolVal, _ := strconv.ParseBool(strings.TrimSpace(line3))
// TODO: Создать боксы для каждого значения с помощью NewBox
// TODO: Вывести описание каждого бокса с помощью метода Describe
// Использовать переменные, чтобы избежать ошибок компиляции (удалите эти строки при реализации)
_ = intVal
_ = strVal
_ = boolVal
// Пример формата вывода:
// fmt.Println(box.Describe())
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП в Go
Внешние файлыРабочее пространство и модули GoПакеты и импортыЭкспортируемые и неэкспортируемые именаВведение в ООП в GoСтруктуры как классыОпределение методов структурПолучатели-указатели и получатели-значенияИнициализация структурФункции-конструкторыИтоги — Простой калькулятор4Интерфейсы
Введение в интерфейсыНеявная реализацияИнтерфейс как контрактПустой интерфейс (any)Утверждение типаПереключатель типовКомпозиция интерфейсовИнтерфейсы Stringer и ErrorПовторение: Калькулятор фигур7Инкапсуляция
Экспортируемые и неэкспортируемые поляИнкапсуляция на уровне пакетовГеттеры и сеттерыСокрытие информации в GoИтоги — Записи о студентах10Обобщения (Generics) (Go 1.18+)
Введение в GenericsПараметры типовОграничения типовОбобщенные структурыОбходной путь для обобщенных методовИтоги — Обобщенная коллекция13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн Abstract FactoryПаттерн ObserverПаттерн Strategy2Глубокое погружение в типы и структуры
Базовые и составные типыОпределение пользовательских типовТеги структурАнонимные структурыВложенные структурыНулевые значения и значения по умолчаниюПовторение — Контактная книга5Композиция вместо наследования
Почему в Go нет наследованияОсновы встраивания структурПродвижение методовВстраивание нескольких структурВстраивание против агрегацииЗатенение встроенных методовИтоги — Иерархия сотрудников8Обработка ошибок и ООП
Интерфейс errorПользовательские типы ошибокОбертывание ошибок (fmt.Errorf)Sentinel-ошибкиerrors.Is() и errors.As()Panic, Defer и RecoverИтоги — Парсер файлов11Стандартная библиотека и ООП
io.Reader и io.Writersort.InterfaceИнтерфейс fmt.Stringerencoding/json со структурамиИнтерфейс http.HandlerПовторение: модели REST API14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикMiddleware как Декоратор3Указатели и память
Основы указателей в GoУказатели на структурыПередача по значению и по ссылкеФункция new()Сборка мусора в GoПовторение: Конструктор связного списка6Полиморфизм в Go
Полиморфизм через интерфейсыУтиная типизация в GoПравила реализации интерфейсовПолиморфные коллекцииВнедрение зависимостейИтоги — Обработчик платежей9Конкурентность и ООП
Основы горутинКаналы и взаимодействиеБуферизованные и небуферизованные каналыОператор selectsync.Mutex и sync.RWMutexsync.WaitGroupПроектирование потокобезопасных структурПовторение — Worker PoolПотренируйтесь самостоятельно: Онлайн-компилятор Go