You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Intuitively, you would expect the loop to run 1,000,000 times, but every once in a while it would need to wait for the other goroutine to finish its operation.
Instead, the program gets stuck. This is because a goroutine runs mux.Lock(), but doesn't run mux.Unlock() until the function is ready to exit. But before that happens, mux.Lock() gets run again.
One of the other most common uses for defer is to free resources. Resources should be freed as soon as possible in order for optimal performance. A resource cannot be used outside of its variable scope (obviously), so therefore a defer should free the resource once it is out of scope.
For instance:
funcmain() {
// ...ifcondition {
r, err:=getSomeResource()
iferr!=nil {
panic(err)
}
deferr.Close()
// do stuff with `r`...// under this proposal, r.Close() would be run right here
}
// we cannot do stuff with `r` as it is now out of scope,// so it should be freed at this point.someLongRunningOperation()
// in current Go, r.Close() would be run all the way down here. What a waste!
}
The text was updated successfully, but these errors were encountered:
I think in a number of cases making defer scope-based would result in a lot less clear code, if not break things entirely. For somewhat contrived example,
funcLogSomething(w io.Writer, useSecondFileboolean) error {
ifuseSecondFile {
file, err:=os.OpenFile(SecondaryLogFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
iferr!=nil {
returnerr
}
// Under this proposal, this would be impossible. Even if you move// file into the parent scope, you still can't conditionally defer// it. You'd have to provide a default dummy value with a no-op// Close() method in order to defer it outside the if statement.deferfile.Close()
w=io.MultiWriter(w, file)
}
// Log something or something.
}
Sometimes you want the defer in a loop to wait until the end of the function.
func readAndJoin(files []string) []byte {
var readers []io.Reader
for _, file := range files {
f, _ := file.Open(file)
defer f.Close()
readers = append(readers, f)
}
var b []byte
.. read from readers into b ..
return b
}
You guys are right, there are quite a few examples where a scope-based defer just doesn't work (especially conditional defers...) which I didn't think about. There is also a pretty basic solution, which while it is a bit inconvenient, is a lot less inconvenient than the solutions required for trying to weasel around a block-scoped defer.
Currently,
defer
runs once the function exits.I argue that it would be much more intuitive if
defer
ran once it was out-of-scope.For instance, a "solution" to a classic concurrent programming example, adding 2,000,000 to an integer, one at a time, concurrently
Intuitively, you would expect the loop to run 1,000,000 times, but every once in a while it would need to wait for the other goroutine to finish its operation.
Instead, the program gets stuck. This is because a goroutine runs
mux.Lock()
, but doesn't runmux.Unlock()
until the function is ready to exit. But before that happens,mux.Lock()
gets run again.One of the other most common uses for
defer
is to free resources. Resources should be freed as soon as possible in order for optimal performance. A resource cannot be used outside of its variable scope (obviously), so therefore adefer
should free the resource once it is out of scope.For instance:
The text was updated successfully, but these errors were encountered: