# [译] part 7: golang 包

https://juejin.im/post/5cbdf9076fb9a0321141ae0b

## main 函数和 main 包

geometry.go 的代码如下，

1. //geometry.go
2. package main
3. import "fmt"
4. func main() {
5. fmt.Println("Geometrical shape properties")
6. }

1. src
2. geometry
3. gemometry.go
4. bin
5. geometry

## 创建自定义包

1. //rectprops.go
2. package rectangle
3. import "math"
4. func Area(len, wid float64) float64 {
5. area := len * wid
6. return area
7. }
8. func Diagonal(len, wid float64) float64 {
9. diagonal := math.Sqrt((len * len) + (wid * wid))
10. return diagonal
11. }

## 导入自定义包

1. src
2. geometry
3. geometry.go
4. rectangle
5. rectprops.go

import "geometry/rectangle" 是导入 rectangle 包的方式。

1. //geometry.go
2. package main
3. import (
4. "fmt"
5. "geometry/rectangle" //importing custom package
6. )
7. func main() {
8. var rectLen, rectWidth float64 = 6, 7
9. fmt.Println("Geometrical shape properties")
10. /*Area function of rectangle package used
11. */
12. fmt.Printf("area of rectangle %.2f\n", rectangle.Area(rectLen, rectWidth))
13. /*Diagonal function of rectangle package used
14. */
15. fmt.Printf("diagonal of the rectangle %.2f ",rectangle.Diagonal(rectLen, rectWidth))
16. }

1. Geometrical shape properties
2. area of rectangle 42.00
3. diagonal of the rectangle 9.22

## init 函数

1. func init() {
2. }

init 函数用于执行初始化任务，也可用于在执行开始之前验证程序的正确性。

1. 首先初始化包级别变量
2. 接下来调用 init 函数。一个包可以有多个 init 函数（在单个文件中或分布在多个文件中），并按照它们呈现给编译器的顺序调用它们。

1. //rectprops.go
2. package rectangle
3. import "math"
4. import "fmt"
5. /*
7. */
8. func init() {
9. fmt.Println("rectangle package initialized")
10. }
11. func Area(len, wid float64) float64 {
12. area := len * wid
13. return area
14. }
15. func Diagonal(len, wid float64) float64 {
16. diagonal := math.Sqrt((len * len) + (wid * wid))
17. return diagonal
18. }

1. //geometry.go
2. package main
3. import (
4. "fmt"
5. "geometry/rectangle" //importing custom package
6. "log"
7. )
8. /*
9. * 1\. package variables
10. */
11. var rectLen, rectWidth float64 = 6, 7
12. /*
13. *2\. init function to check if length and width are greater than zero
14. */
15. func init() {
16. println("main package initialized")
17. if rectLen < 0 {
18. log.Fatal("length is less than zero")
19. }
20. if rectWidth < 0 {
21. log.Fatal("width is less than zero")
22. }
23. }
24. func main() {
25. fmt.Println("Geometrical shape properties")
26. fmt.Printf("area of rectangle %.2f\n", rectangle.Area(rectLen, rectWidth))
27. fmt.Printf("diagonal of the rectangle %.2f ",rectangle.Diagonal(rectLen, rectWidth))
28. }

1. rectLenrectWidth变量从 main 函数级别移动到包级别。
2. 添加了一个 init 函数。如果rectLenrectWidth小于零则使用log.Fatal函数打印日志并终止。

main 包的初始化顺序是

1. 首先初始化导入的包。因此 rectangle 包首先被初始化
2. 接下来初始化包级别变量rectLenrectWidth
3. 调用 init 函数
4. 最后调用 main 函数

1. rectangle package initialized
2. main package initialized
3. Geometrical shape properties
4. area of rectangle 42.00
5. diagonal of the rectangle 9.22

1. rectangle package initialized
2. main package initialized
3. 2017/04/04 00:28:20 length is less than zero

## 使用_符号

Go 中导入包并且不在代码中的任何位置使用它是非法的。如果你这样做，编译器会报错。这样做的原因是为了避免大量未使用的包显著增加编译时间。用以下代码替换 geometry.go 中的代码，

1. //geometry.go
2. package main
3. import (
4. "geometry/rectangle" //importing custom package
5. )
6. func main() {
7. }

1. package main
2. import (
3. "geometry/rectangle"
4. )
5. var _ = rectangle.Area //error silencer
6. func main() {
7. }

1. package main
2. import (
3. _ "geometry/rectangle"
4. )
5. func main() {
6. }