go lint 工具范围关闭检测

Posted

技术标签:

【中文标题】go lint 工具范围关闭检测【英文标题】:go lint tools range closure detection 【发布时间】:2020-10-05 09:35:10 【问题描述】:

尝试将gonnel 用于某些隧道。试图打开 2 个隧道,然后当它们关闭时,我注意到日志包说试图关闭同一个隧道两次。通过查看代码,似乎(其中一个)问题是:

我想我会利用 staticcheck、golangci-lint 甚至去 vet 让它突出这个问题,这样我就可以更有信心解决这个问题。但是,当我运行这些工具时,我会得到以下输出:

golangci-lint:

去看兽医:

静态检查:

还尝试使用 -loopclosure 运行 go vet,但我仍然没有得到任何输出。难道其中一个工具不应该说 go func 需要将迭代器变量作为参数传递吗?如果有帮助,我正在运行 go 1.14.3 darwin/amd64,并且还尝试在 goland 中导入代码,但我没有收到该代码段的检查警告。我感觉我可能做错了什么,你能看出是什么吗?

谢谢!

【问题讨论】:

忽略 linter 警告,一个问题可能是 c.Tunnel 包含重复项。我注意到AddTunnel 不检查重复插入。如果有重复,t.IsCreated 上可能会有比赛。由于CloseTunnelDisconnectAll 不以线程安全的方式使用t.IsCreated,因此如果两次在c.Tunnel 中,则可能会为同一隧道生成两个闭包goroutine。 你使用的是什么版本的 Go(和 linter)?一些较旧的警告没有。 使用go 1.14.3staticcheck 2020.1.4golangci-lint has version 1.27.0 built from fb74c2e on 2020-05-13T18:45:55Z Shouldn't one of the tools say that the go func needs the iterator variable passed as param? 这是基于意见的,您应该与库作者讨论。 【参考方案1】:

是的,正确。这个问题在 Gophers 中很常见 (What happens with closures running as goroutines?)!

去看兽医的问题:

    https://github.com/golang/go/issues/21412 https://github.com/golang/go/issues/16520

因此,您似乎看不到 go vet 的输出,因为 goroutine 在 if 块中。您可以尝试不使用if 块吗?我认为您的问题更相关Issue 21412


同样适用于golangci/govet:

引用golangci/govet/rangeloop.go的代码:

This file contains the code to check range loop variables bound inside function
literals that are deferred or launched in new goroutines. We only check
instances where the defer or go statement is the last statement in the loop
body, as otherwise, we would need whole-program analysis.

另外,我的建议是检查隧道是否打开,然后只关闭它。您可能会重复条目,所以再次有可能出现一些问题。并首先修复作为 goroutine 错误运行的闭包。

因此,这是一个示例,其中 if 块是 go vet 工作方式的差异化因素。

使用if 块,go vet 不返回任何内容
package main

import (
        "fmt"
        "sync"
)

func main() 
        fruits := []string"orange", "apple"
        var wg sync.WaitGroup
        for _, fruit := range fruits 
                if true 
                        wg.Add(1)
                        go func() 
                                fmt.Println(fruit)
                                wg.Done()
                        ()
                
        
        wg.Wait()

没有if 块,go vet 返回loop variable fruit captured by func literal
package main

import (
        "fmt"
        "sync"
)

func main() 
        fruits := []string"orange", "apple"
        var wg sync.WaitGroup
        for _, fruit := range fruits 
                wg.Add(1)
                go func() 
                        fmt.Println(fruit)
                        wg.Done()
                ()
        
        wg.Wait()

【讨论】:

@geo 如果这个答案对你有帮助,你能接受吗?谢谢! 嘿@shmsr,抱歉,没有机会尝试!会在早上尝试然后接受,谢谢!

以上是关于go lint 工具范围关闭检测的主要内容,如果未能解决你的问题,请参考以下文章

Facebook Debugger lint 工具获取 HTTP 206 - 未检测到 Open Graph 元标记(其他工具可以)

工利其器Android Lint篇——为Android量身定做的静态代码审查工具

检测内存泄漏

Go资源竟态检测工具:race detetor

Vue Eslint语法检测工具

Vue Eslint语法检测工具