美文网首页Golang语言社区Go语言用例Golang与区块链
go语言build和install, 以及包名的关系

go语言build和install, 以及包名的关系

作者: CodingCode | 来源:发表于2017-10-30 15:15 被阅读9次

    这篇文件介绍go build与go install的用法,包括包和可执行文件的关系,包的命名关系。

    用法

    $ go build/install <packages>

    说明:
    <package>是从$GOPATH/src路径下面的目录名,例如:

    1. $ go install lib
      编译安装package lib
    2. $ go install lib2 lib/util
      同时编译安装lib2和lib/util两个package。

    另外,如果当前工作路径已经在package目录下面了,则可以不需要指定package名,例如:

    $ cd $GOPATH/lib/util
    $ go install
    

    功能:

    1. build
      对于库,只是验证编译能够成功,不会生成目标库文件。
      对于可执行程序,会生成目标可执行文件,并放在当前目录下面。

    2. install
      对于库,会生成目标库文件,并且放置到$GOPATH/pgk目录下。
      对于可执文件,会生成目标可执行文件,并且放置到$GOPATH/bin目录下。

    包名和目录名的关系

    1. 一个目录名下只能有一个package,否则编译器会报错。
    2. 也建议一个package名的内容放在一个目录下面,便于项目管理。
    3. 建议目录名和package名相同,便于项目管理。

    包名和目录名不相同时他们的使用场景:

    • 目录名使用在文件层面,例如库的安装路径名和库文件名(pkg路径),以及被引用(import)时的路径。
    • 包名使用在代码层面,例如引用包的函数时。

    举个例子:
    包定义如下:

    $cat src/lib/lib.go
    package lib2
    
    func LibFunc(i int) int {
        return i + 1
    }
    

    这个包定义的目录为lib,但是lib.go里面定义的package又是lib2,我们看这个包编译完之后生成的文件是什么:

    $ find ./pkg/
    ./pkg/
    ./pkg/linux_amd64
    ./pkg/linux_amd64/lib.a
    

    我们看到生成的包名是lib.a,这是根据包目录名生成的;这些都是文件层面的,所以都是有lib。

    再看引用方式如下:

    $ cat src/main/main.go
    package main
    
    import (
        "fmt"
        "lib"
    )
    
    func main() {
        fmt.Printf("i=%d\n", lib2.LibFunc(1))
    }
    

    第一个我们看到在import语句里面指定的是lib,这是生成的包的目录名字,这是文件层面的,而调用函数LibFunc的时候又是使用的lib2,这个名字又是包名,而不是目录名了,因为这是代码层面的。

    为什么会这样,我们改一个代码再编译就看出来了,我们把引用的地方改一下:

    $ cat src/main/main.go
    package main
    
    import (
        "fmt"
        "lib"
    )
    
    func main() {
        fmt.Printf("i=%d\n", lib.LibFunc(1))
    }
    

    对比前面的代码,就是把lib1.LibFunc(1)改成了lib.LibFunc(1),编译:

    $ go run src/main/main.go
    # command-line-arguments
    src/main/main.go:5: imported and not used: "lib" as lib2
    src/main/main.go:9: undefined: lib in lib.LibFunc
    

    注意看这第一个编译错误,编译器隐式的把import进来的lib映射成了lib2,这也就是为什么后面需要用lib2而不是lib;编译器为什么能这么做呢,因为编译器能够解析lib.a的内容,当然就能知道这里面定义的真正包是lib2。

    此处结论就是:建议目录和包是一一对应关系,即一个目录对应一个包,一个包对应一个目录,并且目录名和包名一致,谢谢

    go如何区分库和可执行程序目录

    都是一个目录,go编译器如何区分这是一个库目录还是一个可执行文件目录,因为库目录需要安装到$GOPATH/pkg路径下面,可执行程序需要安装到$GOPATH/bin路径下面。规则就是:

    • 这个目录的包名字是不是main
      如果是,则go认为这是一个可执行程序目录
      如果不是,go就认为这是一个库目录

    注意这里包名并不是目录名,和不和路径相关,也就是说不管是项目顶级目录下的main,还是某个路径下面的main,例如lib/main都认为是main,只要代码层面的名字是main,即是可执行程序。

    这里强调一点:

    • 包对应一个目录,并不包含路径信息。
    • 包只包含一个目录下面的文件,并不包含子目录。

    即,每一个目录都是独立编译成一个包文件的,这个包文件并不包含目录下面的子目录,因为子目录是另一个独立的包,需要独立编译;文件路径上的包含关系并没有包之间的包含关系,包没有路径递归这个属性。

    库的使用

    库编译安装完之后方在$GOPATH/pkg目录下面按照原来的路径关系存放,go编译器在编译可执行程序时先到$GOPATH/pkg目录下面搜索相应的库文件,如果搜到到则直接使用,如果没有搜搜到则到对应的源代码目录($GOPATH/src)下面编译出库文件,然后再编译可执行文件。

    相关文章

      网友评论

        本文标题:go语言build和install, 以及包名的关系

        本文链接:https://www.haomeiwen.com/subject/fkbppxtx.html