Ответ
В Go для работы с размерами канала используются две встроенные функции: cap() для ёмкости и len() для текущего количества элементов.
1. Ёмкость канала — cap()
Функция cap() возвращает ёмкость (capacity) канала, то есть размер его буфера. Это максимальное количество элементов, которое можно отправить в канал без блокировки.
- Для буферизированных каналов
cap()вернет размер буфера, указанный при создании. - Для небуферизированных каналов
cap()всегда возвращает0.
// Буферизированный канал
bufChan := make(chan int, 5)
fmt.Println(cap(bufChan)) // Вывод: 5
// Небуферизированный канал
unbufChan := make(chan int)
fmt.Println(cap(unbufChan)) // Вывод: 0
2. Текущее количество элементов — len()
Функция len() возвращает текущее количество элементов, находящихся в буфере канала.
ch := make(chan int, 3)
fmt.Printf("Ёмкость: %d, Длина: %dn", cap(ch), len(ch))
ch <- 1
ch <- 2
fmt.Printf("Ёмкость: %d, Длина: %dn", cap(ch), len(ch))
<-ch
fmt.Printf("Ёмкость: %d, Длина: %dn", cap(ch), len(ch))
// Вывод:
// Ёмкость: 3, Длина: 0
// Ёмкость: 3, Длина: 2
// Ёмкость: 3, Длина: 1
⚠️ Важное замечание: В реальном коде редко полагаются на len() для управления потоком данных в конкурентных программах. Состояние канала может измениться между вызовом len() и следующей операцией. Вместо этого используются блокирующие операции чтения/записи, select или закрытие канала для синхронизации горутин.
Ответ 18+ 🔞
Ах ты ж ёпта, ну и тема у нас сегодня — каналы в Go и как их, блядь, измерить! Сидишь ты такой, пишешь горутины, швыряешь туда-сюда данные, а потом бац — надо понять, сколько в канале места осталось, а сколько уже забито. Ну, хули, Go и тут не подвёл, дал две простые, как три копейки, функции: cap() и len().
1. Ёмкость, сука — cap()
Вот смотри, cap() — это типа твой личный замерщик буфера. Он тебе честно скажет, насколько канал, блядь, растягивается. Создал буферизированный канал на пять мест — cap() вернёт пятёрку, как миленький. А если ты жмот и сделал небуферизированный, ну, тот, что без буфера, — получишь ноль, ебать мои старые костыли! Всё честно.
// Канал с буфером, как порядочный
bufChan := make(chan int, 5)
fmt.Println(cap(bufChan)) // Выведет: 5, ядрёна вошь!
// А это — канал-спринтер, без буфера
unbufChan := make(chan int)
fmt.Println(cap(unbufChan)) // Выведет: 0, хуй с горы, неожиданно?
2. Текущая загрузка — len()
А вот len() — это уже сторож на складе. Он тебе докладывает: «Шеф, у нас вот столько-то ящиков уже лежит!». Отправил два значения — len() подскочил до двух. Забрал одно — упал до одного. Всё логично, пиздец как просто.
ch := make(chan int, 3)
fmt.Printf("Ёмкость: %d, Длина: %dn", cap(ch), len(ch)) // Пусто, блядь!
ch <- 1
ch <- 2
fmt.Printf("Ёмкость: %d, Длина: %dn", cap(ch), len(ch)) // Опа, уже два!
<-ch
fmt.Printf("Ёмкость: %d, Длина: %dn", cap(ch), len(ch)) // Забрали один, остался один.
// Вывод:
// Ёмкость: 3, Длина: 0
// Ёмкость: 3, Длина: 2
// Ёмкость: 3, Длина: 1
⚠️ А теперь, сука, важный момент на посошок! В реальной жизни, в этих ваших конкурентных плясках, на len() полагаться — это как ходить по охуенно тонкому льду. Пока ты смотришь на длину, канал уже может измениться — туда долбанут новое значение или выдернут старое. Поэтому умные дядьки используют не эти замеры, а нормальную синхронизацию: блокирующие операции, select или закрытие каналов. А len() — это так, для справки, чтоб в отладке посмотреть, что творится в этой кухне. Чисто прикинуть, не переполняется ли буфер, пока ты кофе пил.