Какова роль и назначение ключевого слова `default` в конструкции `select` в Go? Опишите основные сценарии его использования.

Ответ

Ключевое слово default в конструкции select в Go используется для выполнения неблокирующей операции. Если на момент выполнения select ни один из case (операций с каналами) не готов к выполнению, исполняется блок default.

Без default, select будет блокировать текущую горутину до тех пор, пока одна из операций с каналами не станет доступной.

Основные сценарии использования default:

  1. Неблокирующее чтение из канала: Позволяет попытаться прочитать данные из канала, но не ждать их, если канал пуст. Это полезно для "опроса" (polling) состояния канала.

    select {
    case msg := <-messages:
        fmt.Println("Получено сообщение:", msg)
    default:
        // Выполняется немедленно, если в канале 'messages' нет данных
        fmt.Println("Нет новых сообщений.")
    }
  2. Неблокирующая отправка в канал: Позволяет попытаться отправить данные в канал. Если канал не имеет буфера или его буфер полон, отправка не будет блокировать горутину, а вместо этого выполнится default.

    // ch - канал с буфером размера 1
    ch := make(chan string, 1)
    ch <- "первое сообщение"
    
    select {
    case ch <- "второе сообщение":
        fmt.Println("Второе сообщение успешно отправлено")
    default:
        // Канал полон, отправка заблокировалась бы без default
        fmt.Println("Не удалось отправить второе сообщение, канал полон.")
    }

Итог:

Использование default превращает блокирующий select в неблокирующий, что является ключевым механизмом для реализации таких паттернов, как опрос каналов, попытка отправки данных без риска блокировки и предотвращение deadlock в некоторых сценариях.