Skip to content
This repository has been archived by the owner on Nov 2, 2023. It is now read-only.
/ noloopclosure Public archive

noloopclosure is a linter that disallow reference capture of loop variable inside of a closure.

License

Notifications You must be signed in to change notification settings

fatanugraha/noloopclosure

Repository files navigation

test status

noloopclosure

noloopclosure is a linter that disallow reference capture of loop variable inside of a closure.

This linter can prevent bugs introduced by a very popular gotcha in Go by disallowing implicit reference capture when creating closure inside a loop.

Installation

go install github.com/fatanugraha/noloopclosure/cmd/noloopclosure@latest

Difference with go vet's loopclosure

loopclosure will only complain if the captured loop variable is inside of a function closure that preceded by go and defer keyword and is the last statement in the loop's block (reference).

This linter complain each time it found any captured loop variable inside a function closure. This linter is helpful if you have utilities that abstracts the go behavior, for example:

func main() {
	for i := 0; i < 10; i++ {
		runInGoroutine(func() { fmt.Println(i) })
	}
}

func runInGoroutine(f func()) {
	go f()
}

will pass the go vet's check while fails the noloopclosure check.

It's generally a good idea (unless every bit of performance matters) to extract the function creation part inside your loop so that you don't accidentally capture the reference and cause unwanted bugs. For example, code above can be re-written as:

func main() {
	for i := 0; i < 10; i++ {
		runInGoroutine(newIntPrinter(i))
	}
}

func newIntPrinter(i int) func() {
    func() { fmt.Println(i) }
}

func runInGoroutine(f func()) {
	go f()
}

About

noloopclosure is a linter that disallow reference capture of loop variable inside of a closure.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages