Ownership and lifecycle
exitpolicy
Checks process termination that bypasses registered defers.
What it detects
os.Exit and log.Fatal terminate the process without running deferred calls.
Return an error through the normal call stack when cleanup has already been
registered on the current path.
Checks
| Check | What it detects |
|---|---|
skipped-defer |
Reports immediate process termination that bypasses an earlier defer. |
Why this is flagged
Immediate process termination skips deferred cleanup. Buffered output may be lost, temporary files may remain, and resources may not be closed cleanly.
Further reading: os.Exit,
log.Fatal.
How to fix it
Return an error through the normal call stack so deferred cleanup can run. If the process must exit, do it once at the top level, after the function that owns the cleanup has returned.
Examples
Flagged code
func run() { file, _ := os.CreateTemp("", "state") defer file.Close() // gohawk: log.Fatal exits without running an earlier defer log.Fatal("startup failed")}Accepted code
func runSafely() error { file, err := os.CreateTemp("", "state") if err != nil { return err } defer file.Close() return nil}