Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

19.03.2024

GC в Go посеред функції

Сьогодні розвідав дуже несподівану особливість Go: невикористана змінна може бути вивільнена ще до виходу з (теоретичної) області видимості.

Як це було. Є такий випадково хибний тест на обмеження кількості підключень. Він створює декілька одночасних підключень, і нарешті на N-те сервер повинен відмовити. Але на практиці час від часу не відмовляє.

Спочатку думав, що то проблеми синхронізації, чи затримки. Розставив логи. Виявилося, що в хибному випадку клієнти закривають підключення ще до останньої перевірки — тому під час перевірки вже є вільні місця. Шукав налаштування клієнта, які можуть змусити його відключитися. Не знайшов — та й за лічені секунди ніякі клієнти не відключаються.

Нарешті, випадково помітив, що якщо звернутися до масиву клієнтів після перевірки (хоч би для логування), то тест не хибиться! Виявилося, що це Go бачить, що я не звертаюся до масиву, та вважає його вільним для збірки сміття. Причому все це в межах однієї функції! Там, де візуально змінна “ще могла б знадобитися.”

Зробив демонстраційний скрипт, який ще раз підтверджує цю поведінку. (До речі, щоб побачити запуски GC, можна запустити з опцією GODEBUG=gogc=1)

Виходить, не дарма Go не дозволяє мати в коді невикористані змінні — бо життєвий цикл змінної вимірюється по використанню, а не по області видимості.