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

🤖🚫 Контент вільний від AI. Цей пост на 100% написаний людиною, як і все на моєму блозі. Насолоджуйтесь!

02.11.2023

Робота з вводом/виводом в Golang

В продовження вчорашньої теми

Головна різниця в роботі вводу/виводу в Golang в тому, що тут код, що блокує, нічим не відрізняється від синхронного. Ніякої спеціальної відмітки для очікування не потрібно. Це, звісно, спрощує код. Бо ввід/вивід — це не тільки читання файлів, але й спілкування з клієнтами та з базою даних, та й взагалі з будь-яким зовнішнім ресурсом.

Можна подумати, що це властивість компільованої чи системної мови програмування, але ні: наприклад, в Ruby IO теж виглядає синхронно, а у Swift - потребує асинхронного коду або колбеків. Ось такий аспект дизайну мови.

Але то не єдина різниця між Go та JavaScript. Менш помітно те, що в JavaScript ввід/вивід працює за принципом push, а в Go - pull. В JavaScript ми можемо зробити запит на читання та займатись чимось іншим — допоки не буде викликаний наш обробник. В Go виклик Read зупиняє виконання програми. З читанням файлів це менш помітно, але з сокетами ми можемо чекати досить довго.

Тому в Go все ж використовують асинхронний код, але не конкретно для вводу/виводу, а для одночасного виконання. Наприклад, типовий сервер буде запускати горутіну для кожного підключеного клієнта: комунікація через кожне підключення відбуватиметься послідовно, та блокування очікуване.

Для читання та запису в Go є інтерфейси io.Reader та io.Writer. Так саме як і в JavaScript, вони можуть приховувати будь-яку логіку. На відміну від JavaScript, немає “дуплексного” інтерфейсу для перетворень. Щоб додати до даних перетворення, зазвичай загортають читач та повертають новий читач: наприклад, bufio.NewReader додасть до будь-якого читача буферизацію.