美文网首页
go package包的使用以及路径问题

go package包的使用以及路径问题

作者: leejnull | 来源:发表于2020-01-08 22:24 被阅读0次

    前言

    一开始学 Go,非常晕的就是 package 包的问题,我们知道 Go 有一个很简单的文件可见性规则:首字母大写即对外可见,但是不知道对外是对什么外。
    以及我在一个 ch1 目录下,创建一个 demo.go 文件,在输入 package 时, VS 又会自动提示 package ch1,这个和 main 又有什么关系呢?
    我在一个 ch1 目录下写了一个 demo.go 文件,里面有一个函数,我在 ch2/demo2.go 里面想用又该怎么 import 呢?
    带着这些疑问,这次来系统的了解一下~

    Go的环境变量

    在我们安装完 go 之后,输入

    go env
    

    会输出一大堆信息,其中 GOPATH 就是我们的工作区,我们写了一个 demo.go 文件,其中如果 import 了一些第三方库,运行的时候就会先从 GOROOT 中找,如果没有找到会再去 GOPATH 里面找
    我们可以通过修改 GOPATH 添加额外的工作区,在你的 .zshrc / .bash_profile 文件里面

    export GOPATH="/Users/lijun/go:/Users/lijun/Documents/Go/golearning"
    

    引入第三方库

    一般我们通过

    go get -u github.com/julienschmidt/httprouter
    

    这个指令下载的第三方库都会保存在 GOPATH 第一个工作区指定的 src 目录下
    只需要在项目里

    import "github.com/julienschmidt/httprouter"
    

    就能使用这个第三方包了

    有时候 go get 下载失败,可以手动去 GitHub 下载源代码,放到对应目录下,记住路径要和 GitHub 上的文件路径一致

    在当前文件使用另一个文件定义的函数或变量

    • 同级目录
      在class文件夹下新建 demo.go 和 demo_lib.go
    // demo_lib.go
    package main
    
    import "fmt"
    
    func hello(name string) {
        fmt.Printf("Hello, %s!\n", name)
    }
    
    // demo.go
    package main
    
    import "flag"
    
    var name string
    
    func init() {
        flag.StringVar(&name, "name", "everyone", "The greeting object.")
    }
    
    func main() {
        flag.Parse()
        hello(name)
    }
    

    当在一个同级目录下面,有一个 package main 实现了 main() 函数的时候,这是作为程序的唯一入口。在同级目录下,别的文件也必须 package main,且不能再实现 main() 函数,否则提示 redeclared 错误。
    此时 demo_lib.go 文件里的变量和函数对 demo.go 都是可见的。且不受可见性影响

    • 不同级目录
      现在我们在 class 文件夹下新建 lib 文件夹,在新建一个 demo2_lib.go 文件,demo2_lib 现在就有两种可能了
      1. package main 并且实现 main() 函数,那么它就是另一个新程序的入口了,内部的函数和变量就不能被别的文件 import
      2. package 包名,这样的话是可以被外部使用,但是我们需要把首字母大写,对外部可见(这里了解了对外部是指对别的包而言),我们现在测试这种情况
    package lib
    
    import "fmt"
    
    func Hello(name string) {
        fmt.Println("Hello, %s!\n",)
    }
    

    如果 demo.go 要使用 demo2_lib 下的 Hello 函数,需要导入这个包。这时候我们需要 go install 一下

    go install class/lib
    

    后面的路径是要导入的包的相对路径,执行完之后,会在我们的工作区下生成 pkg/darwin_amd64/class/lib.a


    2019-08-21-11.png

    在 demo.go 导入即可

    package main
    
    import (
        "class/lib"
        "flag"
    )
    
    var name string
    
    func init() {
        flag.StringVar(&name, "name", "everyone", "The greeting object.")
    }
    
    func main() {
        flag.Parse()
        lib.Hello(name)
    }
    

    到这里我们算是完成了一个供外部调用的包的程序

    这里有个疑问

    我在 class/lib 文件夹下创建的 demo2_lib.go 文件,并且 package lib,package的包名和所在文件夹名有必然联系吗?

    // demo2_lib.go
    package lib2
    
    import "fmt"
    
    func Hello(name string) {
        fmt.Printf("Hello, %s!\n", name)
    }
    

    改成 lib2 试一下
    go install 后面跟的是路径,所以依然是 class/lib

    go install class/lib
    

    在主函数什么都不改变,调用

    go run demo.go
    

    此时提示

    # command-line-arguments
    ./demo.go:4:2: imported and not used: "class2/lib" as lib2
    ./demo.go:18:2: undefined: lib
    

    从字面上理解一下的话,第一个是说导入了但是没有把 class2/lib 当做 lib2 来使用,第二行说没有定义的 lib

    emmm~~~

    我记得 import 包的时候可以起个别名的,试一下

    package main
    
    import (
        lib2 "class/lib"
        "flag"
    )
    
    var name string
    
    func init() {
        flag.StringVar(&name, "name", "everyone", "The greeting object.")
    }
    
    func main() {
        flag.Parse()
        lib2.Hello(name)
    }
    

    继续运行一下,输出结果

    lijun:class2/ $ go run demo.go     
    Hello, everyone!
    

    可以了!!!
    想一下,我们主要做了什么,和之前有什么不同
    在路径 class/lib 下,demo2_lib.go 文件没有 package lib,而是 package lib2

    // 原来
    package lib
    
    // 现在
    package lib2
    

    go install class/lib 这个步骤没有变也变不了。
    最后在 main 函数中调用,原来是

    import "class/lib"
    
    lib.Hello(name)
    

    现在是

    import lib2 "class/lib"
    
    lib2.Hello(name)
    

    也就是说,当我们要在一个项目里新建一个 tool 文件夹放我们的工具包,我们可以不 package tool,而是可以写一个别的包名,依然可以使用,只不过在使用的时候,import 的还是 pkg 下的路径,但是要给这个 import 设置它真正的包名,即这里的 lib2

    总结

    算是弄明白了 Go 下的文件引用,以及 GOPATH 的设置。
    同一级目录下只能有一个 main,且别的文件对它都是可见的,不需要设置大小写都可以被访问到,不同级目录,根据首字母大小写可见,还需要 go install一下,再 import 对应路径,包名可以和路径不一致,但是要设置别名。
    简单了解后,如果还有别的疑惑欢迎大家一起探讨!

    来自 https://leejnull.github.io/2019/08/21/2019-08-21-1/

    相关文章

      网友评论

          本文标题:go package包的使用以及路径问题

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