Запятая-ok при assertion

Конструкция запятая-ok (comma-ok idiom) при assertion (утверждении типа) позволяет безопасно проверить, хранит ли интерфейс значение конкретного типа. В отличие от обычного утверждения типа, которое вызывает панику при несовпадении, эта конструкция возвращает два значения: извлеченное значение и булево значение, указывающее на успех операции.

Синтаксис

govalue, ok := interfaceVar.(TargetType)

Где interfaceVar — переменная типа интерфейса, TargetType — тип, на который мы пытаемся утвердить, value — значение целевого типа (если утверждение успешно), ok — булево значение, которое равно true, если интерфейс содержит значение типа TargetType, и false в противном случае.

Пример

Давайте проверим, содержит ли интерфейс значение типа int:

gopackage main

import "fmt"

func main() {
  var i interface{} = 42

  value, ok := i.(int)
  if ok {
    fmt.Println("Value is int:", value)
  } else {
    fmt.Println("Value is not int")
  }
}

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

go"Value is int: 42"

Пример

Давайте проверим, содержит ли интерфейс значение типа string, когда на самом деле там хранится int:

gopackage main

import "fmt"

func main() {
  var i interface{} = 12345

  value, ok := i.(string)
  if ok {
    fmt.Println("Value is string:", value)
  } else {
    fmt.Println("Value is not string")
  }
}

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

go"Value is not string"

Обратите внимание, что в этом случае паники не произошло, а переменная value содержит нулевое значение для типа string (пустую строку), так как утверждение не удалось.

Пример

Часто конструкцию с запятой-ok используют в сочетании с switch для проверки нескольких возможных типов:

gopackage main

import "fmt"

func main() {
  var i interface{} = []int{1, 2, 3, 4, 5}

  switch v := i.(type) {
  case int:
    fmt.Println("int:", v)
  case string:
    fmt.Println("string:", v)
  case []int:
    fmt.Println("slice of ints:", v)
  default:
    fmt.Println("unknown type")
  }
}

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

go"slice of ints: [1 2 3 4 5]"

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

  • конструкцию type-assertion,
    которая выполняет утверждение типа без проверки
  • конструкцию type-switch,
    которая позволяет выполнять действия в зависимости от типа
  • понятие пустого интерфейса,
    который может хранить значение любого типа
  • тип any,
    который является псевдонимом для пустого интерфейса в Go 1.18+