Мне нравится, как Go обрабатывает внутреннее мультиплексирование ввода-вывода, которое epoll
и другие механизмы и планируют зеленые потоки (здесь процедура go), что дает свободу писать синхронный код.
Я знаю, что TCP-сокеты равны non-blocking
, а read
выдаст EAGAIN
, если данные недоступны. Учитывая это, conn.Read(buffer)
обнаружит это, а блокирует процедуру go, выполняя чтение соединения без данных, доступных в буфере сокета . Есть ли способ, чтобы остановить такие рутины без закрытия основного соединения. Я использую пул соединений, поэтому закрытие TCP-соединения для меня не имеет смысла, и я хочу вернуть это соединение обратно в пул.
Вот код для симуляции такого сценария:
func main() {
conn, _ := net.Dial("tcp", "127.0.0.1:9090")
// Spawning a go routine
go func(conn net.Conn) {
var message bytes.Buffer
for {
k := make([]byte, 255) // buffer
m, err := conn.Read(k) // blocks here
if err != nil {
if err != io.EOF {
fmt.Println("Read error : ", err)
} else {
fmt.Println("End of the file")
}
break // terminate loop if error
}
// converting bytes to string for printing
if m > 0 {
for _, b := range k {
message.WriteByte(b)
}
fmt.Println(message.String())
}
}
}(conn)
// prevent main from exiting
select {}
}
Какие другие подходы я могу использовать, если это невозможно:
1) Позвоните syscall.Read
и обработайте это вручную. В этом случае мне нужен способ проверить, является ли сокет читаемым перед вызовом syscall.Read
, в противном случае я буду тратить ненужные циклы ЦП. Для моего сценария, я думаю, что я могу пропустить событие опроса на основе событий и продолжать вызывать syscall.Read
, так как в моем случае использования всегда есть данные.
2) Любые предложения:)