Golang学习笔记-1.10 包的理解

本文系第十篇Golang语言学习教程

什么是包?为什么用包?

Go语言的包和其他语言的库或模块类似,目的是为了支持封装、模块化、单独编译和代码重用。
一个包的源代码保存在一个或多个以.go为文件后缀名的源文件中。
每个包对应一个独立的名字空间,例如,在image包中和在unicode/utf16包中的Decode函数是不同的。要在外部引用该函数,需要image.Decode形式访问。

main函数和main包

所有可执行的Go程序必须包含一个main函数,这个函数是程序的入口,main函数必须放在main包中。
在1.2,hello,world中有写过编译代码go buildgo install两种方式,以及区别。
例1:

package main  //每一个 Go 文件都应该在开头进行 package name 的声明(译注:只有可执行程序的包名应当为 main)。表明该文件属于哪个包。
import "fmt"  //引入了 fmt 包,用于在 main 函数里面打印文本到标准输出。

func main() {  
     fmt.Println("Hello,World!")
}
//func声明函数main,调用 fmt 包的 Println 函数做标准输出。{}中的内容称之为函数体。

创建自定义的包

我们将构建一个计算矩形面积和对角线的应用程序,更好的理解包。(本例来源于Go中文网)

我们将组织代码,使得所有与矩形有关的功能都放入rectangle包中。
创建一个自定义包rectangle,它有一个计算矩形面积和对角线的函数。
创建一个geometry的文件夹,并在其中创建一个rectangle文件夹,用于存放包的源文件,在这个文件夹中,所有文件都会以package rectangle开头,因为他们属于rectangle包。
创建名为rectprops.go的文件,编写代码
例2:

//rectprops.go
package rectangle

import "math"

func Area(len, wid float64) float64 {  //定义面积的函数
    area := len * wid
    return area
}

func Diagonal(len, wid float64) float64 {  //定义对角线的函数
    diagonal := math.Sqrt((len *len) + (wid * wid))  //Sqrt函数用来计算平方根
    return diagonal
}

再上面程序中,创建了两个函数用于计算Area和Diagonal。
矩形的面积= 长 * 宽
矩形的对角线= (长的平方 + 宽的平方)的平方根
math包下面的Sqrt函数用于计算平方根.

导入自定义包

为了使用自定义包,首先需要在可执行文件中导入包,导入的语法为 import path。我们必须指定自定义包相对于工作区内src文件夹的相对路径。
在geometry文件夹中创建可执行文件geometry.go用于导入自定义包。
例3

//geometry.go
package main

import (
    "fmt"
    "geometry/rectangle" //导入自定义包
)

func main() {
    var rectLen, rectWidth float64 = 6, 7  //定义长、宽的变量
    /* %.2f 会将浮点数精确到小数点后两位*/
    fmt.Printf("area of rectangle %.2f\n",rectangle.Area(rectLen, rectWidth))  //调用函数计算面积
    fmt.Printf("diagonal of rectangle %.2f\n",rectangle.Diagonal(rectLen,rectWidth))  //调用函数计算对角线
}

上面的代码导入了rectangle包,并调用了里面的 Area 和 Diagonal 函数,得到矩形的面积和对角线。Printf 内的格式说明符 %.2f会将浮点数截断到小数点两位。应用程序的输出为:

area of rectangle 42.00
diagonal of rectangle 9.22

导出名字

我们在创建函数的文件中,将两个函数名AreaDiagonal,首字母大写。这是因为在Go中,任何以大写字母开头的变量或函数,都是被导出的名字。其他包只能访问到被导出的函数或变量。main包要访问函数AreaDiagonal,因此首字母必须大写。

init函数

任何包都可以包含一个init函数,可用于执行初始化任务,也可以用于验证程序正确性。init不应有任何返回值类型和参数,init函数行书如下:

func init() {
}

包的初始化顺序如下:

  • 首先初始化包级别(Package Level)的变量
  • 紧接着调用 init 函数。包可以有多个 init 函数(在一个文件或分布于多个文件中),它们按照编译器解析它们的顺序进行调用。

如果一个包导入了另一个包,会先初始化被导入的包。
尽管一个包可能会被导入多次,但是它只会被初始化一次。
为了理解 init 函数,我们接下来对程序做了一些修改。
首先在 rectprops.go 文件中添加了一个 init 函数。
例4

// rectprops.go
package rectangle

import "math"  
import "fmt"

func init() {  
    fmt.Println("rectangle package initialized")
}
func Area(len, wid float64) float64 {  
    area := len * wid
    return area
}

func Diagonal(len, wid float64) float64 {  
    diagonal := math.Sqrt((len * len) + (wid * wid))
    return diagonal
}

我们添加了一个 init 函数,它仅打印 rectangle package initialized

接下来修改main包,我们都知道矩形的长宽都应该大于0,我们将在 geometry.go中使用 init 函数和包级别的变量来检查矩形的长和宽。
例5

//geometry.go
package main

import (
    "fmt"
    "geometry/rectangle"
    "log"
)

/*
 *1.包级别变量
*/
var rectLen, rectWidth float64 = 6, 7  //定义长、宽的变量

/*
 *2.init函数检查长宽是否大于0
*/
func init()  {
    if rectLen <= 0 {
        log.Fatal("length is less than zero")
    }
    if rectWidth <= 0 {
        log.Fatal("width is less than zero")
    }
}

func main() {

    /* %.2f 会将浮点数精确到小数点后两位*/
    fmt.Printf("area of rectangle %.2f\n",rectangle.Area(rectLen, rectWidth))  //调用函数计算面积
    fmt.Printf("diagonal of rectangle %.2f\n",rectangle.Diagonal(rectLen,rectWidth))  //调用函数计算对角线
}

我们对 geometry.go 做了如下修改:

  • 变量 rectLen 和 rectWidth 从 main 函数级别移到了包级别。
  • 添加了 init 函数。当 rectLen 或 rectWidth 小于 0 时,init 函数使用 log.Fatal 函数打印一条日志,并终止了程序。

以上矩形长宽大于0 ,所以输出正常,无报错,接着我们将长修改为负数:

var rectLen, rectWidth float64 = -6, 7

运行程序将会报错:length is less than zero

空白标识符

我们在程序的开发活跃阶段,常常要导入很多包,却暂不使用它,但是运行的时候go会报错imported and not used...,那么遇到这种情况可以使用空白标识符_
例6

package main

import (  
    "geometry/rectangle" 
)

var _ = rectangle.Area // 错误屏蔽器

func main() {

}

var _ = rectangle.Area 这一行屏蔽了错误。运行时不会再报错。

以上为学习Golang 包的理解篇

你可能感兴趣的:(Golang学习笔记-1.10 包的理解)