tg-me.com/golang_for_two/36
Last Update:
Note #12: defer statements in infinite loops
Длинный стек отложенных вызовов может занимать много памяти, как Вы уже догадались такой код будет стремительно течь 💦:
$ cat main.go
package main
func g()
func f() {
for {
defer g()
}
}
func main() {
f()
}
Отловить данную проблему поможет статический анализатор:
deferlint:
go vet -vettool=$(which deferlint) .
# github.com/andriisoldatenko/us/🇺🇦 Go на двоих/com.golang_for_two
./main.go:10:4: defer in loop found "defer g()"
либо staticcheck
staticcheck
main.go:10:4: defers in this infinite loop will never run (SA5003)
Иногда данная ситуация абсолютно валидная, поэтому
staticcheck
пытается найти циклы без условий или брейков, чтобы отметить такой кейс, это помогает бороться с ложными срабатываниями.Кстати,
deferlint
- отличный пример, как написать свой линтер[1].Исправить данную ситуацию возможно, обернув
defer
в анонимную функцию, чтобы гарантированно ваша отложенная функция была вызвана вовремя.func f() {
for {
func(){
defer g()
}()
}
}
Потенциально, любой цикл, а особенно бесконечный, может служить причиной утечки памяти.
defer
следует гарантированно выполнять сразу же после того, как мы освободили ресурс, который нам уже больше не нужен. А иногда - это может происходить в цикле.Links:
[1] Если вдруг вы пропустили статью о том, как написать свой линтер использую go/analysis, то вот https://arslan.io/2019/06/13/using-go-analysis-to-write-a-custom-linter/
BY 🇺🇦 Go for two :)
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Share with your friend now:
tg-me.com/golang_for_two/36