第四章:代码的组织——包与可见性

Go通过“包”(package)来组织代码,这与PHP的namespaceComposer的自动加载机制有相似之处,但规则更严格。

4.1 包(Package) #

  • 一个目录下的所有.go文件必须属于同一个包。
  • 包名建议与目录名相同。
  • 可执行程序的入口包必须是main

4.2 导入(Import) #

我们使用import关键字来导入其他包,以便使用它们提供的功能。

package main

import (
    "fmt" // 标准库包
    "math" // 标准库包
    "strings" // 标准库包

    // 导入第三方包(需要先通过 `go get` 获取)
    // "github.com/google/uuid"
)

func main() {
    fmt.Println("Hello")
    fmt.Println(math.Pi)
    fmt.Println(strings.ToUpper("hello world"))
}

4.3 可见性(导出规则) #

这是Go一个非常独特且重要的设计!在PHP中,我们用public, protected, private关键字来控制属性和方法的可见性。

在Go中,规则极其简单:一个标识符(如变量名、常量名、类型名、函数名、方法名)的可见性,取决于其首字母的大小写。

  • 首字母大写Public(公共的)。这个标识符可以被任何其他包导入后访问。我们称之为“导出的”(Exported)。
  • 首字母小写Private(私有的)。这个标识符只能在它自己所在的包内部访问。

示例

假设我们有一个mymath包:

// mymath/calculator.go

package mymath

// Pi 是大写字母开头,所以是导出的,可以在包外访问
const Pi = 3.14159

// version 是小写字母开头,所以是私有的,只能在mymath包内部使用
var version = "1.0"

// Add 函数是导出的
func Add(a, b int) int {
    return a + b
}

// subtract 函数是私有的
func subtract(a, b int) int {
    return a - b
}

main包中使用它:

// main.go

package main

import (
    "fmt"
    "your_module_name/mymath" // 假设mymath在你的模块下
)

func main() {
    fmt.Println(mymath.Pi)     // 正确
    fmt.Println(mymath.Add(5, 3)) // 正确

    // 下面两行会导致编译错误
    // fmt.Println(mymath.version)  // 错误: version是未导出的
    // fmt.Println(mymath.subtract(5, 3)) // 错误: subtract是未导出的
}

这个设计强制你思考哪些是你包的公共API,哪些是内部实现细节,使得代码边界非常清晰。