17-Golang包管理

包是go最小的分发单位。
包是函数和数据的集合,将有相关特性的函数和数据放在统一的文件/目录进行管理,每个包都可以作为独立的单元维护并提供给其他项目进行使用。

包声明
Go 源文件都需要在开头使用 package 声明所在包,包名告知编译器哪些是包的源代码用于编译库文件,其次包名用于限制包内成员对外的可见性,最后包名用于在包外对公开成员的访问。
包名使用简短的小写字母,常与所在目录名保持一致,一个包中可以由多个 Go 源文件,但必须使用相同包名。

导入
在使用包时需要使用 import 将包按路径名导入,再通过包名调用成员。
可通过 import 每行导入一个包,也可使用括号包含所有包并使用一个 import 导入。

工作目录结构:

  • bin: 用于放置发布的二进制程序
  • pkg: 用于放置发布的库文件
  • src: 用于放置源代码

运行:

  1. 将 源码 目录添加到 GOPATH 环境变量中
  1. 编译&运行

使用 go build 编译二进制文件
命令:go build gpkgmain
说明:编译路径 gpkgmain 下的包,main 包,则在当前目录产生以 pkgmain 命名的二进制程序

使用 go run 运行二进制文件
命令:go run gpkgmain

使用 go install 编译并发布二进制文件
命令:go install gpkgmain
说明:编译并发布路径 gpkgmain 下的包,main 包,则在将编译后的以 pkgmain 命名的二进制程序拷贝到 bin 目录

使用 go install 编译发布库文件
命令:go install gpkgname/pkg01
说明:编译并发布路径 gpkgname/pkg01 下的包,非 main 包,则在将编译的以包名命名的库文件拷贝到 pkg/GOOS_GOARCH 目录下

使用 go install 编译发布所有二进制和库文件
命令:go install ./…
说明:编译并发布当前路径下的所有二进制程序和库文件
注意:Go 语言不允许交叉导入包

    1. go get
    go get 下载目录到gopath的第一个路径中
    go env
    echo $GOPATH
    go get github.com/WPFS/gopkg
    */
    
    2. 包的导入方式
    /*
    (1) 绝对导入
    import (
        "fmt"
        "github.com/WPFS/gopkg"
    )
    (2) 相对导入,不建议使用
    import (
        "fmt"
        "./github.com/WPFS/gopkg"
    )
    (3) 别名导入解决多个包或者包内函数名冲突
    import (
         lgopkg "gopkg"
        "github.com/WPFS/gopkg"
    )
    (4) 点导入 调用函数,可省略包名. 不建议使用
    import (
        "fmt"
        . "github.com/WPFS/gopkg"
    )
    (5) 下划线导入 (使用下划线作为别名)调用包的初始化函数init。
         init函数是初始化包使用,无返回值,无参数。建议每个包只定义一个
         init函数在import包时自动被调用(const-->var-->init)
        import (
        "fmt"
        _"gopkg"
        "github.com/WPFS/gopkg"
    )
    */
    
    3. 包-成员可见性
    /*
    Go语言使用名称首字母大小写来判断对象(常量、变量、函数、类型、结构体、方法等)的访问权限,
    首字母大写标识包外可见(公开的),否则仅包内可访问(内部的)
    */
    
    4. main包和main函数
    /*
    main包用于声明告知编译器将包编译为二进制可执行文件
    在main包中的main函数是程序的入口,无返回值,无参数
    */
    
    5. 包管理
    /*
    (1)gopath
    (2)gopath+vendor
        将项目依赖包拷贝到项目下的vendor目录,在编译时使用项目下vendor目录中的包进行编译
        解决的问题依赖包过多,在使用第三方包时需要使用go get进行下载
        第三方包在go get下载后不能保证开发和编译时版本的兼容性
        查找顺序
            当前包下的vender目录查找
            向上级目录查找,直到gopath/src/vender目录
            在gopath目录查找
            在goroot目录查找
        go get常用参数
            -d 仅下载依赖包
            -u 更新包并安装
            -x 打印执行的命令
            -v 打印构建的包
            -insecure 允许使用http协议下载包
        第三方包查找地址
        https://godoc.org
        https://gowalker.org
    (3)go modules机制
        a)优势
        不用设置GOPATH,代码可任意放置
        自动下载依赖管理
        版本控制
        不允许使用相对导入
        replace机制
    
        1. 初始化 go mod init [module name]
        2. 编写main程序
        3. go build 
        4. 包管理 go mod tidy
        5. go mod edit -replace=golang.org/x/crypto=github.com/golang/crypto@latest
        6. go build
    
        第三方包:
        在使用 go mod tidy、go build、go test、go list命令会自动将第三方依赖包写入到go.mod文件中同时下载第三方依赖包到GOPATH/pkg/mod/cache目录,
        并在当前模块目录生成一个构建状态跟踪文件go.sum,文件中记录当前module所有的顶层和间接依赖,以及这些依赖的检验和
    
        常用命令
        go mod tidy  整理依赖模块
        go mod vendor  将依赖模块拷贝到模块中vendor目录
        go build 编译当前模块
        go build ./... 编译当前目录下的所有模块
        go build -mod=vendor 使用当前模块下的vendor目录中的包进行编译
        go mod download   仅下载第三方模块
        go mod grapha     打印所有第三方模块
        go list -m -json all  显示所有模块信息
        go mod edit       修改go.mod文件
            -require=package@version
            -replace=old_package@version=new_package@version
    
    replace (
        golang.org/x/crypto => github.com/golang/crypto v0.0.0-20190701094942-4def268fd1a4
        golang.org/x/net => github.com/golang/net v0.0.0-20190628185345-da137c7871d7
        golang.org/x/sync => github.com/golang/sync v0.0.0-20190423024810-112230192c58
        golang.org/x/sys => github.com/golang/sys v0.0.0-20190626221950-04f50cda93cb
        golang.org/x/text => github.com/golang/text v0.3.2
        golang.org/x/tools => github.com/golang/tools v0.0.0-20190706070813-72ffa07ba3db

    )
    
    6. testing 单元测试和基准测试(性能)
        a) 创建testcalc/calc目录
        b) 运行go mod init testcalc
        b) 编写calc.go文件
            package calc
    
            func Add(x, y int) int {
                if x > 0 {
                    return x + y
                } else {
                    return x
                }
            }
    
            func Fact(n int) int {
                if n == 0 {
                    return 1
                }
                return n * Fact(n-1)
            }
        c) 编写calc_test.go
            package calc
    
            import "testing"
    
            func TestAdd(t *testing.T) {
                if 4 != Add(1, 3) {
                    t.Errorf("1+3 = 4")
                }
            }
    
            func TestFlag(t *testing.T) {
                if -1 != Add(-1, 3) {
                    t.Errorf("-1 + any != -1")
                }
            }
    
            func BenchmarkFact(b *testing.B) {
                for i := 1; i <= 10; i++ {
                    Fact(i)
                }
            }
    
        d)  go test testcalc/calc
    
        go test testcalc/calc --coverprofile=cover.out  # 测试覆盖率
        go tool cover -html cover.out
      go test testcalc/calc -bench .
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • src目录:源代码 pkg目录:go install的代码包。“.a” bin目录:go install安装后,g...
    宋song一阅读 248评论 0 0
  • go语言的发展极其迅速,短短几年便已经历了高速变迁和进化,可能仅仅是几年前的项目,在现在的开发者眼中看起来都像是“...
    Katou_Megumi阅读 7,390评论 0 0
  • 本文记录下学习 golang官方文档[https://go.dev/doc/code] 里 go tools 和包...
    周群力阅读 1,211评论 0 0
  • 大多数现代的类 Unix 操作系统都提供了一种中心化的机制用来搜索和安装软件。软件通常都是存放在存储库中,并通过包...
    等会再说阅读 1,408评论 4 17
  • 包是函数和数据的集合,将有相关特性的函数和数据放在统一的文件/目录进行管理,每个包都可以作为独立的单元维护并提供给...
    imsilence阅读 633评论 0 0