Переключатели типов (type switch) являются формой преобразования: они принимают интерфейс и, для каждого case в switch, в некотором смысле, преобразовывают его в тип этого case. Вот упрощенная версия того, как код в fmt.Printf
превращает значение в строкe с использованием переключателя типа. Если это уже строка, мы хотим, чтобы фактическое значение строки содержалось в интерфейсе, тогда как если оно имеет метод String
мы хотим получить результат вызова метода.
type Stringer interface {
String() string
}
// Значение, предоставленное вызывающим.
var value interface{}
switch str := value.(type) {
case string:
return str
case Stringer:
return str.String()
}
Первый case находит конкретное значение; второй преобразует интерфейс в другой интерфейс.
Что если есть только один тип, который нас интересует? Если мы знаем, что значение содержит string
а мы просто хотим его извлечь? Переключатель типа с одним case подойдет, как и утверждение типа. Утверждение типа принимает значение интерфейса и извлекает из него значение указанного явного типа. Синтаксис заимствует из условия, открывающего переключатель типа, но с явным типом вместо ключевого слова type
:
value.(typeName)
и результатом является новое значение со статическим типом typeName
. Этот тип должен быть конкретным типом, поддерживаемым интерфейсом, или вторым интерфейсом типа, в который может быть преобразовано значение. Чтобы извлечь строку, которую, как нам известно, находится в значении, мы могли бы написать:
str := value.(string)
Но если окажется, что значение не содержит строку, программа завершится с ошибкой во время выполнения. Чтобы избежать этого, используйте идиому «comma, ok», чтобы безопасно проверить, является ли значение строкой:
str, ok := value.(string)
if ok {
fmt.Printf("string value is: %q\n", str)
} else {
fmt.Printf("value is not a string\n")
}
Если утверждение типа не выполнено, str
все еще будет существовать и иметь тип string, но будет иметь нулевое значение, пустую строку.
В качестве иллюстрации возможности приведем if-else
утверждение, которое эквивалентно переключателю типа, который мы привели в начале поста.
if str, ok := value.(string); ok {
return str
} else if str, ok := value.(Stringer); ok {
return str.String()
}
Читайте также:
Комментариев нет:
Отправить комментарий