Golang 提供了包管理方式,方便项目的分类管理。

你可以理解为这是进阶版的 Get Start

项目结构

  • 项目结构包括:
    • 项目路径:项目目录在此电脑上的位置。
    • 项目名go mod init 时为项目命的名,与项目路径呈对应关系,通常与项目路径最后一级命名相同。
    • 包路径:导包时使用包路径,包是最后一级目录,包路径为 标准库路径项目名/包相对于项目路径。其中 main 包 路径应为 项目名/src
    • 包名:打包时定义包名,程序内使用包名区别各个包,与包路径呈对应关系,通常与包路径最后一级命名相同。其中 main 包 包名应为 main
    • 源文件:写有代码的 .go 文件,一个包可以有多个源文件,一个包内所有源文件的包名必须相同,不同包间所有源文件的包名必须不同。

新建项目、打包、导包

新建项目

  • 如果一个项目涉及多个自定义包,应该新建项目。
  • 在执行 go mod init 命令后,项目目录下会生成 go.mod 文件,该目录下所有文件属于该项目。
1
2
cd {项目路径}
go mod init {项目名}
1
2
cd D:/Go/Project/Test
go mod init testProject

打包

  • 所有文件必须打包,打包语句必须位于程序第一行。
  • main 是特殊的包,main 包必须包含 main 函数(main 函数不能有任何参数和返回值),非 main 包不得包含 main 函数。
1
package <包名>  // 一般以小写字母开头, 打包时定义包名
1
package main

导包

  • 导包 import 应该紧跟在打包语句后,注意导包时使用包路径而非包名。
  • 如果导包使用别名,访问包内对象应使用别名;否则,访问包内对象应使用包名。
1
2
3
4
5
6
7
import "<包路径>"  // 单个包导入
import (
"<包路径1>"
"<包路径2>"
...
) // 多个包导入
import <别名> "<包路径>" // 使用别名
1
2
3
4
import (
"fmt" // 标准库包
"testProject/packageDirectory1" // 自定义包
)

运行项目

1
2
3
cd {项目路径}/src
go build
./src.exe

全局作用域

  • 直接定义在包中的函数、变量都是全局变量。

  • 全局变量一旦被定义将始终存在,直到程序终止。

  • 全局变量可以在包之间共享,它分为:

    • 受保护(Protected),所有内部包可以相互访问。所有小写字母开头的全局变量、函数是受保护的。
    • 公有(Public),允许外部包访问共有成员。所有大写字母开头的全局变量、函数是公有的。

项目案例

  • 注意:项目名通常与项目路径最后一级命名相同,包名通常与包路径最后一级命名相同。但在此案例中为了区分两者的区别,使用不同的命名。

新建项目

1
2
cd D:/Go/Project/TestProject
go mod init test

生成 go.mod 文件:

1
2
3
4
module test

go 1.20

构建项目结构

  • D:/Go/Project/TestProject
    • packageDirectory1
      • packageFile1.go
      • packageFile2.go
    • packageDirectory2
      • packageFile3.go
      • packageFile4.go
    • src
      • hello.go
      • main.go

编写源代码

  • ./packageDirectory1/packageFile1.go
1
2
3
4
5
6
7
8
9
package packageName1

func Add(x, y int) int {
return x + y
}

func mul(x, y int) int {
return x * y
}
  • ./packageDirectory1/packageFile2.go
1
2
3
4
5
package packageName1  // 同包不同源文件必须使用相同包名

func Mul(x, y int) int {
return mul(x, y) // 包内可直接访问受保护对象
}
  • ./packageDirectory2/packageFile3.go
1
2
3
4
5
package packageName2  // 不同包的源文件间必须使用不同包名

func Sub(x, y int) int {
return x - y
}
  • ./packageDirectory2/packageFile4.go
1
2
3
4
5
package packageName2

func Div(x, y int) int {
return x / y
}
  • ./src/hello.go
1
2
3
4
5
6
7
package main

import "fmt"

func hello() {
fmt.Println("Hello World!")
}
  • ./src/main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"fmt" // 标准库包
p1 "test/packageDirectory1" // 项目名/包路径
p2 "test/packageDirectory2"
)

func main() {
fmt.Println(p1.Add(3, 7))
fmt.Println(p1.Mul(3, 7)) // 包外只能访问公有对象, p1.mul(3, 7) 是错误的
fmt.Println(p2.Sub(3, 7))
fmt.Println(p2.Div(3, 7))
hello() // 包内访问不需要导包
}

编译并运行

1
2
3
cd D:/Go/Project/TestProject/src
go build
./src.exe
1
2
3
4
5
10
21
-4
0
Hello World!