如何查看 Go 项目的大小?

有没有一种简单的方法来检查 Golang 项目的大小?它不是可执行文件,而是我在自己的项目中导入的包。



UYOU
浏览 142回答 3
3回答

慕森王

您可以通过查看目录来查看库二进制文件有多大$GOPATH/pkg(如果$GOPATH未导出go则默认为$HOME/go)。所以要检查一些 http pkgs 的大小gorilla。首先安装它们:$ go get -u github.com/gorilla/mux$ go get -u github.com/gorilla/securecookie$ go get -u github.com/gorilla/sessions我的 64 位 MacOS ( darwin_amd64) 上的 KB 二进制大小:$ cd $GOPATH/pkg/darwin_amd64/github.com/gorilla/$ du -k *284 mux.a128 securecookie.a128 sessions.a编辑:库(包)大小是一回事,但在链接阶段后可执行文件中占用的空间大小可能会有很大差异。这是因为包有自己的依赖关系,随之而来的是额外的包袱,但这些包袱可能会被您导入的其他包共享。一个例子最好地证明了这一点:空去:package mainfunc main() {}http.go:package mainimport "net/http"var _ = http.Servefunc main() {}mux.go:package mainimport "github.com/gorilla/mux"var _ = mux.NewRouterfunc main() {}所有 3 个程序在功能上都是相同的——执行零用户代码——但它们的依赖关系不同。生成的二进制大小为KB:$ du -k *1028    empty5812    http5832    mux这告诉我们什么?核心 go pkgnet/http显着增加了我们的可执行文件的大小。pkgmux本身并不大,但它对 net/httppkg 具有导入依赖性 - 因此它的文件大小也很大。mux然而和之间的差异http仅为20KB,而列出的 mux.a 库文件大小为284KB. 所以我们不能简单地添加库 pkg 大小来确定它们的真实足迹。结论: 在构建过程中,go 链接器会从各个库中剥离大量包袱,但为了真正了解导入某些包的额外重量,我们必须查看 pkg 的所有子依赖项出色地。

交互式爱情

package mainimport (    "flag"    "fmt"    "log"    "os"    "sort"    "golang.org/x/tools/go/packages")func main() {    flag.Parse()    // Many tools pass their command-line arguments (after any flags)    // uninterpreted to packages.Load so that it can interpret them    // according to the conventions of the underlying build system.    cfg := &packages.Config{Mode: packages.NeedFiles |        packages.NeedSyntax |        packages.NeedImports,    }    pkgs, err := packages.Load(cfg, flag.Args()...)    if err != nil {        fmt.Fprintf(os.Stderr, "load: %v\n", err)        os.Exit(1)    }    if packages.PrintErrors(pkgs) > 0 {        os.Exit(1)    }    // Print the names of the source files    // for each package listed on the command line.    var size int64    for _, pkg := range pkgs {        for _, file := range pkg.GoFiles {            s, err := os.Stat(file)            if err != nil {                log.Println(err)                continue            }            size += s.Size()        }    }    fmt.Printf("size of %v is %v b\n", pkgs[0].ID, size)    size = 0    for _, pkg := range allPkgs(pkgs) {        for _, file := range pkg.GoFiles {            s, err := os.Stat(file)            if err != nil {                log.Println(err)                continue            }            size += s.Size()        }    }    fmt.Printf("size of %v and deps is %v b\n", pkgs[0].ID, size)}func allPkgs(lpkgs []*packages.Package) []*packages.Package {    var all []*packages.Package // postorder    seen := make(map[*packages.Package]bool)    var visit func(*packages.Package)    visit = func(lpkg *packages.Package) {        if !seen[lpkg] {            seen[lpkg] = true            // visit imports            var importPaths []string            for path := range lpkg.Imports {                importPaths = append(importPaths, path)            }            sort.Strings(importPaths) // for determinism            for _, path := range importPaths {                visit(lpkg.Imports[path])            }            all = append(all, lpkg)        }    }    for _, lpkg := range lpkgs {        visit(lpkg)    }    return all}

森栏

您可以使用 下载所有imported 模块,然后计算所有不是测试文件的文件go mod vendor的行数:.gopackage mainimport (   "bytes"   "fmt"   "io/fs"   "os"   "os/exec"   "path/filepath"   "strings")func count(mod string) int {   imp := fmt.Sprintf("package main\nimport _ %q", mod)   os.WriteFile("size.go", []byte(imp), os.ModePerm)   exec.Command("go", "mod", "init", "size").Run()   exec.Command("go", "mod", "vendor").Run()   var count int   filepath.WalkDir("vendor", func(s string, d fs.DirEntry, err error) error {      if strings.HasSuffix(s, ".go") && !strings.HasSuffix(s, "_test.go") {         data, err := os.ReadFile(s)         if err != nil {            return err         }         count += bytes.Count(data, []byte{'\n'})      }      return nil   })   return count}func main() {   println(count("github.com/klauspost/compress/zstd"))}
打开App,查看更多内容
随时随地看视频慕课网APP