Закрытие канала в Kotlin
Открытый канал может принимать новые send,
пока его не закроют методом close.
После закрытия передать еще одно значение нельзя,
но элементы, уже лежащие в буфере, остаются
доступны для receive.
Когда буфер пуст и канал закрыт, обычный
receive бросает
ClosedReceiveChannelException. Безопаснее
спросить результат через receiveCatching:
он возвращает объект с признаком закрытия вместо
исключения.
Сначала кладут число, закрывают канал, забирают оставшееся значение и проверяют, что следующий прием видит конец:
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.runBlocking
fun main() {
runBlocking {
val slot = Channel<Int>(1)
slot.send(4)
slot.close()
println(slot.receive())
val tail = slot.receiveCatching()
println(tail.isClosed)
}
}
На консоли сначала 4, затем true
у isClosed. Пустой закрытый канал не
возвращает новых данных - только сигнал, что
передача завершена.
Если после close буфер уже пуст, первый
же receiveCatching сообщает о закрытии
без значения:
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.runBlocking
fun main() {
runBlocking {
val slot = Channel<String>()
slot.close()
val tail = slot.receiveCatching()
println(tail.isClosed)
println(tail.getOrNull())
}
}
Свойство isClosed остается истинным, а
getOrNull дает null. Так отличают
«элемент еще был» от «данных больше не будет».
Канал строк с одним слотом буфера получает
"done", затем закрывается. Выведите
принятое слово и признак закрытия на следующем
безопасном приеме.
Пустой канал целых сразу закрывают в
runBlocking. Напечатайте результат
безопасного приема: закрыт ли канал и какое
значение вернулось, если оно было.