Эта заметка будет очень короткой. Но надеюсь, она кому-то спасёт несколько часов жизни.
У меня был код. К счастью, это было в тесте, а не в боевом коде, поэтому никто не пострадал.
Код создавал http.Server, запускал две гороутинки для обслуживания входящих соединений:
go func() {
srvr.Serve(p)
}()
go func() {
srvr.ServeTLS(e, "", "")
}()
Ну и дальше создавал клиента, делал к серверу обращения (HTTP GET
) попеременно используя http
и https
ну и чего-то там проверял.
Всё прекрасно работало. До обновления с go1.23.8 до go1.24.2, пришедшего с 42-й Федорой.
А потом перестало. Стало время от времени (но отнюдь не всегда) вываливать разнообразные ошибки. Например, вот такие: Get "https://127.0.0.1:46167/": unexpected EOF
. Или такие: Get "https://127.0.0.1:34757/": write tcp 127.0.0.1:54770->127.0.0.1:34757: write: connection reset by peer
. Или даже вот такие, совсем загадочные: Get "https://127.0.0.1:42447/": http2: client conn could not be establish
. HTTP/2 там, разумеется никто не включал и не собирался. А иногда всё работало и тест проходил правильно.
Самое поганое, что ошибка была плавающей.
В общем, не буду грузить подробностями, как я эту ошибку ловил. Но итог такой. Хотя это нигде и не документировано, но одновременно использовать http.Server.Serve и http.Server.ServeTLS на одном и том же экземпляре сервера нельзя. Тот из них, кто успеет прокрутиться первым, чего-то там инициализирует внутри сервера, прежде, чем уйти в accept loop, и второй после этого ломается. Ломается всегда ServeTLS, не-TLS-овскому Serve вроде как пофигу.
Так что будьте осторожны, и надеюсь, что эта заметка сохранила вам несколько часов жизни :)