zoukankan      html  css  js  c++  java
  • [golang note] 包和导入

    package的作用


           √ package是golang最基本的分发单位工程管理中依赖关系的体现

           √ 每个golang源代码文件开头都拥有一个package声明,表示该golang代码所属的package。

           √ 要生成golang可执行程序,必须建立一个名为main的package,并且在该package中必须包含一个名为main()的函数

           √ 在golang工程中,同一个路径下只能存在一个package,一个package可以拆成多个源文件组成。

           √ import关键字导入的是package路径,而在源文件中使用package时,才需要package名。经常可见的import的目录名和源文件中使用的package名一致容易造成import关键字后即是package名的错觉,真正使用时,这两者可以不同。

            

    • 《Go语言编程》中calc实例

    ▶ 工程目录

           <calcproj>
               ├─<src>
                       ├─<calc>
                                ├─calc.go
                       ├─<simplemath>
                                ├─add.go
                                ├─add_test.go
                                ├─sqrt.go
                                ├─sqrt_test.go
               ├─<bin>
               ├─<pkg>

    ▶ 详细源码

           Δ add.go

    package sm
    
    func Add(a int, b int) int {
        return a + b
    }

           Δ sqrt.go

    package sm
    
    import "math"
    
    func Sqrt(i int) int {
        v := math.Sqrt(float64(i))
        return int(v)
    }

           Δ add_test.go

    package sm
    
    import "testing"
    
    func TestAdd1(t *testing.T) {
        r := Add(1, 2)
    
        if r != 3 {
            t.Errorf("Add(1, 2) failed. Got %d, expected 3.", r)
        }
    }

           Δ sqrt_test.go

    package sm
    
    import "testing"
    
    func TestSqrt1(t *testing.T) {
        v := Sqrt(16)
    
        if v != 4 {
            t.Errorf("Sqrt(16) failed. Got %v, expected 4.", v)
        }
    }

           Δ calc.go

    package main
    
    import "os"
    import "fmt"
    import "strconv"
    import "simplemath"
    
    var Usage = func() {
        fmt.Println("USAGE: calc command [arguments] ...")
        fmt.Println("
    The commands are:
    	add	Addition of two values.
    	sqrt	Square root of a non-negative value.")
    }
    
    func main() {
        args := os.Args
        if args == nil || len(args) < 2 {
            Usage()
            return
        }
    
        switch args[1] {
        case "add":
            if len(args) != 4 {
                fmt.Println("USAGE: calc add <integer1> <integer2>")
                return
            }
    
            v1, err1 := strconv.Atoi(args[2])
            v2, err2 := strconv.Atoi(args[3])
            if err1 != nil || err2 != nil {
                fmt.Println("USAGE: calc add <integer1> <integer2>")
                return
            }
    
            ret := sm.Add(v1, v2)
            fmt.Println("Result: ", ret)
        case "sqrt":
            if len(args) != 3 {
                fmt.Println("USAGE: calc sqrt <integer>")
                return
            }
    
            v, err := strconv.Atoi(args[2])
            if err != nil {
                fmt.Println("USAGE: calc sqrt <integer>")
                return
            }
    
            ret := sm.Sqrt(v)
            fmt.Println("Result: ", ret)
        default:
            Usage()
        }
    }

    ▶ 源码说明

           calcproj工程中srcsimplemath目录下只存在sm一个package,而sm包由四个源文件构成。calc.go文件中可以看到import导入的是simplemath而非sm,而在使用sm包中的Add和Sqrt函数时,使用的才是真正的包名sm。

    import关键字


            使用import语句导入源代码文件所依赖的package路径

           √ 不得导入源代码文件中没有用到的package,否则golang编译器会报编译错误。

    • import语法

    ▶ 风格一

    import "package1"
    import "package2"
    import "package3"
    ...

    ▶ 风格二

    import (
        "package1"
        "package2"
        "package3"
        ...
    )

    • import原理

           如果编译时main包导入了其他的包,那么这些包将被依次导入。

           当一个包被导入时,如果该包还导入了其它的包,那么先将其他的包导入进来,然后再对该包的包级常量和变量进行初始化,最后执行init函数(如果存在)。包的导入如上图所示,是一个递归地过程,等所有被导入的包加载完毕,就会对main包中的包级常量和变量进行初始化,然后执行main包中的init函数(如果存在),最后执行main函数。

           如果一个包被多个包同时导入,那么它只会被导入一次。

    • import修饰操作

    • 点(.)操作

           点(.)操作的含义是:点(.)标识的包导入后,调用该包中函数时可以省略前缀包名。点(.)操作的语法为:

    import . "package1"
    import . "package2"
    import . "package3"
    ...
    import (
        . "package1"
        . "package2"
        . "package3"
        ...
    )

           下面的示例中,fmt包将使用点操作省略前缀包名,os包用法保持不变:

    package main
    
    import (
        . "fmt"
        "os"
    )
    
    func main() {
        for _, value := range os.Args {
            Println(value)
        }
    }

    • 别名操作

           别名操作的含义是:将导入的包命名为另一个容易记忆的别名。别名操作的语法为:

    import p1 "package1"
    import p2 "package2"
    import p3 "package3"
    ...
    import (
        p1 "package1"
        p2 "package2"
        p3 "package3"
        ...
    )

           下面的示例中,fmt包将使用别名操作重新命名为f,os包用法保持不变:

    package main
    
    import (
        f "fmt"
        "os"
    )
    
    func main() {
        for _, value := range os.Args {
            f.Println(value)
        }
    }

    • 下划线(_)操作

           下划线(_)操作的含义是:导入该包,但不导入整个包,而是执行该包中的init函数,因此无法通过包名来调用包中的其他函数。使用下划线(_)操作往往是为了注册包里的引擎,让外部可以方便地使用。下划线(_)操作的语法为:

    import _ "package1"
    import _ "package2"
    import _ "package3"
    ...
    import (
        _ "package1"
        _ "package2"
        _ "package3"
        ...
    )
  • 相关阅读:
    Android零基础入门第22节:ImageView的属性和方法大全
    Android零基础入门第21节:ToggleButton和Switch使用大全
    Android零基础入门第20节:CheckBox和RadioButton使用大全
    Android零基础入门第19节:Button使用详解
    Android零基础入门第18节:EditText的属性和使用方法
    Android零基础入门第17节:Android开发第一个控件,TextView属性和方法大全
    Android零基础入门第16节:Android用户界面开发概述
    Android零基础入门第15节:掌握Android Studio项目结构,扬帆起航
    Android零基础入门第14节:使用高速Genymotion,跨入火箭时代
    <bean> 中的单例 和 原型 scope="singleton" //单例 scope="prototype" //原型
  • 原文地址:https://www.cnblogs.com/heartchord/p/5157793.html
Copyright © 2011-2022 走看看