Кроме выхода при возврате из вызываемого обработчика при ошибке чтения или записи - выполняющаяся подпрограмма go не будет автоматически обрабатывать очистку более длительных операций, но Go предоставляет хорошие способы справиться с этим.
Во-первых, если вы не знакомы с контекстным пакетом - это мощный и идиоматический способ синхронизации подпрограмм go с поведением отмены, я настоятельно рекомендую прочитать блог Concurrency GoШаблоны: Контекст .
Что-то вроде следующего:
func MyServiceFunc(ctx context.Context) {
for {
select {
case <-ctx.Done():
break
default:
//do work
}
}
}
func MyRequestHandler(res http.ResponseWriter, req *http.Request) {
MyServiceFunc(req.Context())
//write response...
}
Или вы можете использовать интерфейс CloseNotifier , который также реализует http.ResponseWriter , вы могли бысделать что-то вроде следующего простого примера:
func MyServiceFunc(notifier <-chan bool) {
for {
select {
case <-notifier:
break
default:
//do work
}
}
}
func MyRequestHandler(res http.ResponseWriter, req *http.Request) {
notifier := res.(http.CloseNotifier).CloseNotify()
MyServiceFunc(notifier)
//write response...
}
Или и простой пример, использующий объединение обоих подходов:
func MyRequestHandler(res http.ResponseWriter, req *http.Request) {
notifier := res.(http.CloseNotifier).CloseNotify()
ctx, cancel := context.WithCancel(req.Context())
go func(closer <-chan bool) {
<-closer //the notifer blocks until the send
cancel() //explicitly cancel all go routines
}(notifier)
go MyServiceFunc(ctx)
MyOtherServiceFunc(ctx)
//write response...
}