'go mod vendor'命令的用途是什么?

twh00eeo  于 2022-12-07  发布在  Go
关注(0)|答案(3)|浏览(787)

文件上说
go mod vendor命令在主模块的根目录中构造一个名为vendor的目录,该目录包含支持主模块中包的构建和测试所需的所有包的副本。仅由主模块外部包的测试导入的包不包括在内。
golangbyexample表示:
您还可以将vendor目录签入到VCS(版本控制系统)中。由于依赖项已经存在于签入到VCS中的vendor文件夹中,因此在运行时不需要下载任何依赖项,这一点非常有用
我认为模块(go.modgo.sum)负责版本控制。我还认为依赖项只在我第一次运行程序时下载。
那么,命令go mod vendor有什么用处呢?它的用途或用例是什么?

zvms9eto

zvms9eto1#

Go Modules负责版本控制,但它并不一定会关注模块从互联网上消失或互联网不可用的情况。如果模块不可用,代码就无法构建。
Go Proxy会通过镜像模块在一定程度上减少消失的模块,但它可能不会一直对所有模块都这样做:

为什么以前可用的模块在镜像中不可用?

proxy.golang.org 不会永远保存所有模块。原因有很多,其中一个原因是proxy.golang.org无法检测到合适的许可证。在这种情况下,只有模块的临时缓存副本可用。并且如果它从原始源中被移除并且变得过时,则可能变得不可用。校验和仍将保留在校验和数据库中,无论它们在镜像中是否不可用。
如欲了解更多信息,请访问:https://proxy.golang.org/
另一种方法是派生模块并使用Go Modules replace指令,它允许在不改变代码的情况下将导入路径重定向到go.mod文件中的另一个路径,例如您的fork。这种方法由colm.anseo提供。
关于Internet访问,如果您运行一个大型服务器场,并且需要在多台计算机上使用代码,则从Internet下载到服务器场中的每台计算机可能效率低下,并且存在安全风险。将go mod vendor用于内部存储库并将其复制到其他地方可能效率更高。大型公司使用内部方法将代码部署到其数据中心的多台服务器上。

kkbh8khc

kkbh8khc2#

这个问题给了我一个想法。有时候我想知道一个模块有多“臃肿”,所以我想找到一种方法来查看模块的大小,以及任何第三方导入。为此,我编写了下面的脚本,使用go mod vendor

package main

import (
   "bytes"
   "fmt"
   "io/fs"
   "os"
   "os/exec"
   "path/filepath"
   "strings"
)

func count(mod string) (int, error) {
   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, nil
}

示例:

package main

func main() {
   c, err := count("github.com/corona10/goimagehash")
   if err != nil {
      panic(err)
   }
   println(c)
}
9lowa7mx

9lowa7mx3#

我还认为只有在第一次运行程序时才会下载依赖项
你必须首先考虑到,要运行你首先需要go build。现在go mod ...是一个工具,配置在哪里放置依赖关系,然后整个事情可以建立。但这不是由某人只是有兴趣运行它-但一个程序的开发人员,无论是为开发/测试目的或进一步部署/ci等。
这是最有用的,因为它将允许编辑一个依赖项,并通过这个修改来重建源树。编译器使用模块的默认方式(正如你可能已经看到的)是使用用户home/全局安装,其中1)它没有绑定到项目2)在那里做的更改最终会对系统上共享这些deps的其他构建产生副作用。
所以,在某种程度上,这是唯一的方法,有一个完全自定义的构建和完整的源代码树为您的项目,其中任何文件的任何变化将反映在构建和保持隔离,然而.而且,这是真的唯一的方法,我设想“调试”的依赖关系的意义上,改变代码或添加日志等(消除歧义:这里不讨论使用调试器)。

相关问题