zoukankan      html  css  js  c++  java
  • go包的理解

    结论:

    1. import时指定的字符串,是相对于$GOPATH的目录路径,告诉了go,要去加载这个目录下所有的包文件(不包括子目录中的文件)
    2. 一个目录中所有的源文件(不包括子目录)代表了单独的一个包,这些源文件内的package关键字指出的包名,必须一致,否则无法被使用
    3. import指定的加载目录、目录中的源文件名字、源文件内通过package关键字指定的包名。这三者可以不一样。导入后,根据package指定的包名,来使用包中的导出成员。
    4. 导入两个目录,这两个目录中的源文件内指定的包名,如果出现相同,则导入目录时会失败
    5. 同一个包,间接或直接被导入多次。这个包只会被初始化一次。如init执行一次,包级别变量的内存只会被分配一次,后续要使用的话,则继续使用上次分配时的值。(这个规律和nodejs也是一致的)这也就是为什么使用mysql时,要导入两个包:
      1. import "database/sql"
        import _ "github.com/go-sql-driver/mysql"
      2. 
        第二个包中引用了第一个包,init函数中对第一个包里的数据进行了一些mysql相关的操作。使后续直接使用第一个包时,能关联得上mysql。
      3. 导入第二个包仅仅是为了执行里面的init函数,从而影响第一个包的行为。所以第二个包空导入即可
    6. 当源文件被加载时,文件内的init函数会被自动执行:
      1. 通过import来加载一个目录时,如果这个目录中有多个源文件,则这些源文件中的init函数都会执行,但文件之间的init函数的执行次序不确定,看go加载文件是的顺序
      2. 一个源文件内可以定义多个init函数,多个init函数会按顺序从上往下执行。虽然一个文件内可以定义多个init,但是没有这个必要,把逻辑都集中在一个init函数中,效果一样

    测试1

    $GOPATH目录如下:

    ├─pkg
    └─src
      └─app.go
      └─m1
        └─k1.go

    app.go:

    package main
    
    import "m1"
    
    func main() {
        x1.Show()
    }

     k1.go:

    package x1
    
    import "fmt"
    
    func Show(){
        fmt.Println("show call")
    }

     运行app.go:输出 show call。

    测试2

    在以上的m1目录中,创建一个文件k2.go

    package x2
    
    import "fmt"
    
    func Show(){
        fmt.Println("show call")
    }

    运行app.go提示:app.go:3:8: found packages x1 (k1.go) and x2 (k2.go) in D:GoPathsrcm1

    测试3

    k1和k2文件中,都通过package指定包名为x1。app.go中导入这两个目录,运行报错:

    .app.go:4:8: x1 redeclared as imported package name
    previous declaration at .app.go:3:8
    .app.go:7:2: undefined: "m2".FnInK1

     解决办法:导入的时候,将冲突的包名,重命名为另一个值即可,如以下k2pkg

     测试4

    k1.go:

    package x1
    
    import "fmt"
    
    var x1Data int = 1;
    
    func init(){
        fmt.Println("x1 init call")
        x1Data = 2;
    }
    
    func ShowData(){
        fmt.Println(x1Data)
    }
    
    func SetData(x int){
        x1Data = x;
    }

    k2.go:

    package x2
    
    import "m1"
    import "fmt"
    
    func init(){
        fmt.Println("x2 init call")
        x1.SetData(333)
    }

    app.go:

    package main
    
    import _ "m2"
    import "m1"
    
    func main() {
        x1.ShowData()
    }

    > go run app.go
    x1 init call
    x2 init call
    333

  • 相关阅读:
    java实现二叉树的构建以及三种遍历
    binary-tree-preorder-traversal二叉树的前序遍历
    insertion-sort-list使用插入排序对链表进行排序
    binary-tree-postorder-traversa二叉树的后序遍历
    sort-list
    Redis的数据类型
    在Windows上搭建Redis服务器
    Eureka源码分析
    Eureka概念理解
    Spring Cloud Eureka
  • 原文地址:https://www.cnblogs.com/hellohello/p/10868601.html
Copyright © 2011-2022 走看看