为了账号安全,请及时绑定邮箱和手机立即绑定

如何查看 Go 项目的大小?

如何查看 Go 项目的大小?

Go
UYOU 2023-06-12 17:20:24
有没有一种简单的方法来检查 Golang 项目的大小?它不是可执行文件,而是我在自己的项目中导入的包。
查看完整描述

3 回答

?
慕森王

TA贡献1777条经验 获得超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.a

128 securecookie.a

128 sessions.a

编辑:


库(包)大小是一回事,但在链接阶段后可执行文件中占用的空间大小可能会有很大差异。这是因为包有自己的依赖关系,随之而来的是额外的包袱,但这些包袱可能会被您导入的其他包共享。


一个例子最好地证明了这一点:


空去:


package main


func main() {}

http.go:


package main


import "net/http"


var _ = http.Serve


func main() {}

mux.go:


package main


import "github.com/gorilla/mux"


var _ = mux.NewRouter


func main() {}

所有 3 个程序在功能上都是相同的——执行零用户代码——但它们的依赖关系不同。生成的二进制大小为KB:


$ du -k *


1028    empty

5812    http

5832    mux

这告诉我们什么?核心 go pkgnet/http显着增加了我们的可执行文件的大小。pkgmux本身并不大,但它对 net/httppkg 具有导入依赖性 - 因此它的文件大小也很大。mux然而和之间的差异http仅为20KB,而列出的 mux.a 库文件大小为284KB. 所以我们不能简单地添加库 pkg 大小来确定它们的真实足迹。


结论: 在构建过程中,go 链接器会从各个库中剥离大量包袱,但为了真正了解导入某些包的额外重量,我们必须查看 pkg 的所有子依赖项出色地。


查看完整回答
反对 回复 2023-06-12
?
交互式爱情

TA贡献1712条经验 获得超3个赞

package main


import (

    "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

}


查看完整回答
反对 回复 2023-06-12
?
森栏

TA贡献1810条经验 获得超5个赞

您可以使用 下载所有imported 模块,然后计算所有不是测试文件的文件go mod vendor的行数:.go


package main


import (

   "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"))

}


查看完整回答
反对 回复 2023-06-12
  • 3 回答
  • 0 关注
  • 187 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信