💬 Как устроен сетевой ввод-вывод в Go?



Сетевой ввод-вывод в Go организован через пакет net стандартной библиотеки, который предоставляет обширный API для работы с сетью. Он использует модель неблокирующего ввода-вывода с горутинами для обеспечения масштабируемости и эффективности.



Когда мы создаем сетевое соединение или слушаем порт, каждая операция ввода-вывода (например, чтение или запись данных) может выполняться в отдельной горутине, позволяя обрабатывать множество соединений параллельно без блокировки главного потока выполнения.



Go автоматически управляет множеством горутин, что упрощает написание масштабируемого асинхронного сетевого кода по сравнению с традиционными подходами, основанными на потоках.



📌 Простой пример:



package main



import (

"fmt"

"io"

"net"

"os"

)



func main() {

// Слушаем на порту 8080

listener, err := net.Listen("tcp", ":8080")

if err != nil {

fmt.Println("Ошибка при создании слушателя:", err)

os.Exit(1)

}

defer listener.Close()

fmt.Println("Сервер запущен и слушает на порту 8080")



for {

// Принимаем входящее подключение

conn, err := listener.Accept()

if err != nil {

fmt.Println("Ошибка при принятии подключения:", err)

continue

}



// Обработка подключения в отдельной горутине

go handleConnection(conn)

}

}



// handleConnection обрабатывает отдельное подключение

func handleConnection(conn net.Conn) {

defer conn.Close()

fmt.Println("Подключился клиент:", conn.RemoteAddr().String())



// Отправляем сообщение клиенту

_, err := io.WriteString(conn, "Привет от сервера!\n")

if err != nil {

fmt.Println("Ошибка при отправке сообщения:", err)

return

}



fmt.Println("Сообщение отправлено клиенту:", conn.RemoteAddr().String())

}