【问题标题】:Find dead code in Golang monorepo在 Golang monorepo 中查找死代码
【发布时间】:2016-10-07 18:57:58
【问题描述】:

我的团队将我们所有的 Golang 代码放在一个 monorepo 中。

  • 包含库代码的各种包子目录。
  • cmd 下的二进制文件/服务/工具

我们已经使用了一段时间,正在做一些清理工作。是否有任何工具或技术可以找到cmd 下的二进制文件未使用的功能?

我知道go vet 可以找到包中未使用的私有函数。但是我怀疑我们也导出了也没有使用的库函数。

【问题讨论】:

  • @JimB 欣赏这些想法,谢谢。不幸的是,我们的代码覆盖率参差不齐。 guru 工具可能很有用。

标签: go refactoring


【解决方案1】:

UPD 2020: unused 工具已合并到 staticcheck 中。 不幸的是,v0.0.1-2020.1.4 可能是最后一个支持这个的 特征。 Dominik explains 那是因为检查消耗了很多 资源,很难做到正确。

要获得那个版本:

env GO111MODULE=on go get honnef.co/go/tools/cmd/staticcheck@v0.0.1-2020.1.4

使用它:

$ staticcheck --unused.whole-program=true -- ./...
./internal/pkg/a.go:5:6: type A is unused (U1001)

原始答案如下。


Dominik Honnef 的 unused 工具可能正是您想要的:

可选地通过 -exported 标志,unused 可以将所有参数分析为 单个程序并报告未使用的导出标识符。这对于 检查“内部”包或不导出的大型软件项目 公开的 API,但在组件之间使用导出的方法。

【讨论】:

  • 似乎unused 不再作为独立工具存在,取而代之的是staticcheck。我似乎无法用staticcheck 做到这一点,你知道怎么做吗?
  • 谢谢! $ go run honnef.co/go/tools/cmd/staticcheck --unused.whole-program=true -- ./... 对我来说效果很好!
【解决方案2】:

尝试运行go build -gcflags -live。这会将-live 标志传递给编译器(go tool compile),指示它输出有关活性分析的调试消息。不幸的是,它只会在找到活动代码时打印,而不是死代码,但理论上您可以查看输出中没有显示的内容。

这是一个编译存储在dead.go中的以下程序的示例:

package main

import "fmt"

func main() {
    if true {
        fmt.Println(true)
    } else {
        fmt.Println(false)
    }
}

go build -gcflags -live的输出:

# _/tmp/dead
./dead.go:7: live at call to convT2E: autotmp_5
./dead.go:7: live at call to Println: autotmp_5

如果我没看错的话,第二行表明对convT2E 的隐式调用(它将非接口类型转换为接口类型,因为fmt.Println 采用interface{} 类型的参数)是实时的,并且第三行表明对fmt.Println 的调用是实时的。请注意,它没有fmt.Println(false) 调用是有效的,所以我们可以推断它一定是死的。

我知道这不是一个完美的答案,但我希望它有所帮助。

【讨论】:

    【解决方案3】:

    它有点脏,但对我有用。 我有很多不想手动测试的结构,所以我编写了一个脚本来重命名该结构,然后运行所有测试(ci/test.sh)并在任何测试失败时将其重命名:

    #!/bin/sh
    
    set -e
    
    git grep 'struct {' | grep type | while read line; do
      file=$(echo $line | awk -F ':' '{print $1}')
      struct=$(echo $line | awk '{print $2}') 
    
      sed "s/$struct struct/_$struct struct/g" -i $file
    
      echo "testing for struct $struct changed in file $file"
    
      if ! ./ci/test.sh; then
        sed "s/_$struct struct/$struct struct/g" -i $file
      fi
    done
    

    【讨论】:

      【解决方案4】:

      我使用的一种可靠但不优雅的方法是重命名或注释掉您怀疑可能不会使用的函数,然后重新编译所有内容——没有错误意味着您不需要它们。

      如果需要,它会显示这些函数的调用位置,因此有助于熟悉代码库并了解事物之间的联系。

      【讨论】:

        猜你喜欢
        • 2014-02-17
        • 2023-03-23
        • 2012-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多