sa9010.go (1276B)
1 package sa9010 2 3 import ( 4 "go/ast" 5 "go/types" 6 7 "honnef.co/go/tools/analysis/code" 8 "honnef.co/go/tools/analysis/lint" 9 "honnef.co/go/tools/analysis/report" 10 11 "golang.org/x/tools/go/analysis" 12 "golang.org/x/tools/go/analysis/passes/inspect" 13 ) 14 15 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ 16 Analyzer: &analysis.Analyzer{ 17 Name: "SA9010", 18 Run: run, 19 Requires: []*analysis.Analyzer{inspect.Analyzer}, 20 }, 21 Doc: &lint.RawDocumentation{ 22 Title: `Returned function should be called in defer`, 23 Text: ` 24 If you have a function such as: 25 26 func f() func() { 27 // Do something. 28 return func() { 29 // Do something. 30 } 31 } 32 33 Then calling that in defer: 34 35 defer f() 36 37 Is almost always a mistake, since you typically want to call the returned 38 function: 39 40 defer f()() 41 `, 42 Since: "2026.2", 43 Severity: lint.SeverityWarning, 44 MergeIf: lint.MergeIfAll, 45 }, 46 }) 47 48 var Analyzer = SCAnalyzer.Analyzer 49 50 func run(pass *analysis.Pass) (any, error) { 51 fn := func(n ast.Node) { 52 def := n.(*ast.DeferStmt) 53 if _, ok := pass.TypesInfo.TypeOf(def.Call).Underlying().(*types.Signature); ok { 54 report.Report(pass, def, "deferred return function not called") 55 } 56 } 57 58 code.Preorder(pass, fn, (*ast.DeferStmt)(nil)) 59 return nil, nil 60 }