zoukankan      html  css  js  c++  java
  • [go]go依赖包管理

    运行main.go

    go run单个文件

    testapp $: tree
    .
    └── main.go
    
    //main.go
    
    package main
    
    import "fmt"
    
    func main() {
    	fmt.Println("hello world")
    }
    
    testapp $: go run main.go
    hello world
    

    go run多个文件

    testapp $: tree
    .
    ├── lib.go
    └── main.go
    
    testapp $: cat lib.go
    package main
    
    import "fmt"
    
    func test() {
    	fmt.Println("test func")
    }
    
    testapp $: cat main.go
    package main
    
    import "fmt"
    
    func main() {
        test()
    	fmt.Println("hello world")
    }
    
    testapp $: go run main.go lib.go
    test func
    hello world
    

    go build单个文件

    testapp $: tree
    .
    └── main.go
    
    testapp $: go build main.go
    testapp $: ls
    main	main.go
    
    testapp $: ./main
    hello world
    
    testapp $: go build      //会在当前目录生成可执行文件(跟当前文件夹名字一样)
    testapp $: ls
    main.go	testapp
    
    testapp $: ./testapp
    hello world
    

    go build多个文件

    testapp $: tree
    .
    ├── lib.go
    └── main.go
    
    testapp $: go build main.go
    # command-line-arguments
    ./main.go:6:5: undefined: test
    
    testapp $: go build main.go lib.go
    testapp $: ls
    lib.go	main	main.go
    testapp $: ./main
    test func
    hello world
    
    testapp $: go build
    testapp $: tree
    .
    ├── lib.go
    ├── main.go
    └── testapp
    
    testapp $: ./testapp
    test func
    hello world
    

    go install

    testapp $: go install  //项目不再GOPATH下
    go install: no install location for directory /Users/mao tai/test/testapp outside GOPATH
    	For more details see: 'go help gopath'
    
    //将项目移到GOPATH下
    $: mv testapp $GOPATH/src
    $: cd $GOPATH/src/testapp
    
    maotai@n1 ~/goproject/src/testapp $: go install
    maotai@n1 ~/goproject/src/testapp $: ls
    lib.go	main.go
    
    maotai@n1 ~/goproject/bin $: ./testapp //被安装到了在GOPATH/bin/testapp
    test func
    hello world
    

    go clean

    go clean命令使用的可能不是很多,一般都是利用go clean命令清除编译文件,然后再将源码递交到 github 上

    
    testapp $: go clean -n
    cd /Users/maotai/test/testapp
    rm -f testapp testapp.exe testapp.test testapp.test.exe lib lib.exe
    
    testapp $: go clean -i -n
    cd /Users/maotai/test/testapp
    rm -f testapp testapp.exe testapp.test testapp.test.exe lib lib.exe
    
    testapp $: go clean -x
    cd /Users/maotai/test/testapp
    rm -f testapp testapp.exe testapp.test testapp.test.exe lib lib.exe
    
    -n 把需要执行的清除命令打印出来,但是不执行,这样就可以很容易的知道底层是如何运行的;
    -i 清除关联的安装的包和可运行文件,也就是通过go install安装的文件;
    
    -x 打印出来执行的详细命令,其实就是 -n 打印的执行版本;
    

    go的包管理工具godep和dep

    go包管理的发展

    Go语言从v1.5开始开始引入vendor模式,如果项目目录下有vendor目录,那么go工具链会优先使用vendor内的包进行编译、测试等。
    godep是一个通过vendor模式实现的Go语言的第三方依赖管理工具,类似的还有由社区维护准官方包管理工具dep。

    godep从go 1.0开始就可以使用了,是比较老的包管理工具,早期使用go的人应该都用过godep.
    dep是2017年初才发布的包管理工具,要求go >= 1.7.
    随着go的发展,包管理工具日渐进化, 目前新项目都用go mod管理. 难免一些老项目用vendor等管理.

    // 包管理的发展
    go get(无版本概念) -> vendor(godep/dep) -> go modules
    
    - GOPATH管理(go get)
    - godep
    - dep
    - go mod
    
    // vendor方式 包查找顺序
    
    1. project/vendor
    2. GOPATH/src
    3. GOROOT/src
    

    go get(GOPATH方式)

    A. 所有的第三方包都放在$GOPATH的src目录下。
    B. 如果不同程序依赖的版本不一样,怎么管理?
    C. 每个程序依赖的包,没有版本号的概念。
    
    //设置go get代理
    
    go env -w GOPROXY=https://goproxy.cn,direct
    

    项目组织

    • 适合个人

    • 适合公司

    godep管理依赖

    go get github.com/tools/godep
    
    godep --help
    
    godep save
    

    该命令会在根目录下自动生成一个Godeps和vendor目录,并将项目所依赖的第三方包信息写入Godeps/Godeps.json,同时复制包源码到vendor目录。
    注意:godep save并不会自动从远程下载依赖包,需要我们通过go get或godep get手动下载,godep save只是将下载的包源码复制到vendor目录。

    举个例子

    ├── myapp
    │   └── main.go
    
    //main.go
    package main
    
    import (
        "fmt"
    
        "github.com/shopspring/decimal"
    )
    
    func main() {
        price, err := decimal.NewFromString("136.204")
        if err != nil {         panic(err)
        }
        fmt.Println(price.StringFixed(2))
    }
    
    go get github.com/shopspring/decimal
    godep save
    

    这里我们导入了一个decimal包,通过go get下载下来后,执行godep save,查看项目目录结构:

    myapp
    ├── Godeps
    │   ├── Godeps.json
    │   ├── Readme
    │── vendor
    │   └── github.com
    │       └── shopspring
    │           └── decimal
    │              │── decimal.go
    │              │── LICENSE
    │              │── README.md
    └── main.go
    

    如果我们的项目新增了某些依赖包,只需执行godep save就可以了,非常方便。但这种包管理方式,也有个不好的地方,
    就是除了Godep.json文件,还需要将vendor目录也提交到代码仓库,而且只要变更了引入的第三方包,则要重新提交vendor目录,只有这样才能保证其他人使用的包版本一致。如果引用的包较多,则代码仓库将变得很庞大。

    dep方式

    go get -u github.com/golang/dep/cmd/dep
    
    dep init
    dep init -v
    

    与godep不同的是,dep可以直接从远程下载依赖包,但目前下载的速度较慢,而如果是需要翻墙才能下载的包,那么dep可能会一直堵塞。

    dep init执行完后,查看当前目录结构,dep生成了两个文件和一个vendor目录:

    ├── Gopkg.lock
    ├── Gopkg.toml
    ├── main.go
    └── vendor/
    

    dep是如何下载依赖包的呢?
    dep在下载依赖包时,会先去检查$GOPATH下是否已经存在该包,若存在,则dep直接将其拷贝到vendor目录下;若不存在,则会从远程下载。

    dep status命令用于查看当前项目依赖了哪些包,以及包的版本号:

    ➜  dep status
    PROJECT                        CONSTRAINT     VERSION        REVISION  LATEST   PKGS USED
    github.com/shopspring/decimal  branch master  branch master  16a9418   16a9418  1
    

    dep ensure命令会根据项目代码依赖的包,将对应包信息写入Gopkg.lock文件,将包源码下载到vendor目录,当不再使用某个包时,执行该命令也会将其从vendor中移除,并更新Gopkg.lock文件。但是,dep ensure不会去更新Gopkg.toml。

    那么,dep ensure是如何知道要下载的包的版本号呢?下面要划重点了:dep ensure下载依赖包的版本是根据Gopkg.toml来的,而Gopkg.lock只是用来记录下载的各个依赖包的具体版本信息。

    go mod使用

    拜拜了,GOPATH君!新版本Golang的包管理入门教程

    gopath管理依赖存在的问题:
    0. 项目被强制存放到GOPATH/src下

    1. 项目A依赖v1 项目B依赖v2,将依赖包都存放到 src下会冲突. 因为src下文件名没包含版本信息
    2. 需要手动去下载依赖包
    自动下载依赖包
    项目不必放在GOPATH/src内了
    所以来的第三方包会准确的指定版本号
    对于已经转移的包,可以用replace 申明替换,不需要改代码
    项目内会生成一个go.mod文件,列出包依赖
    

    使用例子

    testapp $: cat main.go
    package main
    
    import (
        "fmt"
    
        "github.com/shopspring/decimal"
    )
    
    func main() {
        price, err := decimal.NewFromString("136.204")
        if err != nil {         panic(err)
        }
        fmt.Println(price.StringFixed(2))
    }
    
    testapp $: go run main.go
    main.go:6:5: cannot find package "github.com/shopspring/decimal" in any of:
    	/usr/local/go/src/github.com/shopspring/decimal (from $GOROOT)
    	/Users/xiaolangma/goproject/src/github.com/shopspring/decimal (from $GOPATH)
    
    testapp $: go mod init testapp
    go: creating new go.mod: module testapp
    
    testapp $: tree
    .
    ├── go.mod
    ├── go.sum
    └── main.go
    
    testapp $: go run main.go
    go: finding github.com/shopspring/decimal latest
    136.20
    
    问题一:依赖的包下载到哪里了?还在GOPATH里吗? 不在。
    使用Go的包管理方式,依赖的第三方包被下载到了$GOPATH/pkg/mod路径下。
    如果你成功运行了本例,可以在您的$GOPATH/pkg/mod 下找到一个这样的包 github.com/astaxie/beego@v1.11.1
    
    问题二: 依赖包的版本是怎么控制的?
    
    可以看到最终下载在$GOPATH/pkg/mod 下的包 github.com/astaxie/beego@v1.11.1
    最后会有一个版本号 1.11.1,也就是说,$GOPATH/pkg/mod里可以保存相同包的不同版本。
    
    //问题三: 可以把项目放在$GOPATH/src下吗? 可以
    
    auto 自动模式下,项目在$GOPATH/src里会使用$GOPATH/src的依赖包,在$GOPATH/src外,就使用go.mod 里 require的包
    on   开启模式,1.12后,无论在$GOPATH/src里还是在外面,都会使用go.mod 里 require的包
    off  关闭模式,就是老规矩。
    
    问题四: 依赖包中的地址失效了怎么办?比如 golang.org/x/… 下的包都无法下载怎么办?
    在go快速发展的过程中,有一些依赖包地址变更了。 以前的做法
    
    方法1: 修改源码,用新路径替换import的地址
    方法2: git clone 或 go get 新包后,copy到$GOPATH/src里旧的路径下 无论什么方法,都不便于维护,特别是多人协同开发时。
    
    replace golang.org/x/text => github.com/golang/text latest
    
    问题五: init生成的go.mod的模块名称有什么用?
    本例里,用 go mod init hello 生成的go.mod文件里的第一行会申明 module hello
    
    因为我们的项目已经不在$GOPATH/src里了,那么引用自己怎么办?就用模块名+路径。
    
    testapp $: go mod vendor //将项目代码中import的第三方包copy到vendor下. 1.便于阅读 2.便于存档提交git.
    testapp $: tree
    .
    ├── go.mod
    ├── go.sum
    ├── main.go
    └── vendor
        ├── github.com
        │   └── shopspring
        │       └── decimal
        │           ├── LICENSE
        │           ├── README.md
        │           ├── decimal-go.go
        │           ├── decimal.go
        │           ├── go.mod
        │           └── rounding.go
        └── modules.txt
    
    //依赖更新
    go get -u          //升级所有依赖
    
    go list -m all     //列出当前依赖
    go ilst -m -u all  //列出可升级的依赖
    
    • incomba

    • 下划线导入

    • 静态导入

    goland使用

    Go进阶21:Goland 6条Tips让编程更有效率
    构造方法
    struct实现接口

  • 相关阅读:
    ATP(excel测试及邮件发送)自己小框架
    logging模块和自动化及日志类的封装
    多线程,多进程(2)
    Python的datetime模块分析
    前端性能优化和测试工具总结
    web前端性能指标、测试方案、优化技巧
    如果一生只有一次翻身的机会,就要用尽全力
    YAML最最基础语法
    CURL常用命令
    Curl学习之使用
  • 原文地址:https://www.cnblogs.com/iiiiiher/p/12290951.html
Copyright © 2011-2022 走看看