0Pricing
Go Academy · 课时

包:组织 Go 代码

包声明、导入与导出名称

包:组织 Go 代码 是 CoddyKit 上的免费 Go Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。

什么是包

每个 Go 源文件都属于一个包。包名出现在每个文件的顶部。包用于组织相关代码并控制可见性:

// file: math/calc.go
package math

// Exported — accessible from other packages (capital letter)
func Add(a, b int) int { return a + b }

// Unexported — package-private (lowercase)
func helper() int { return 42 }

包声明与导入路径

包名(简短名称)不同于导入路径(完整的模块路径或目录):

// Import path: github.com/myapp/util/stringutil
// Package name: stringutil (last segment by convention)
package stringutil

func Reverse(s string) string {
    r := []rune(s)
    for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
        r[i], r[j] = r[j], r[i]
    }
    return string(r)
}

导入包

使用 import 引入其他包。Go 要求所有导入的包都必须被使用:

package main

import (
    "fmt"                         // standard library
    "strings"                     // standard library
    "github.com/myapp/util/math"  // third-party or local
)

func main() {
    fmt.Println(strings.ToUpper("hello"))
    fmt.Println(math.Add(1, 2))
}

导出与未导出标识符

以大写字母开头的标识符是已导出的(公开的)。以小写字母开头的是未导出的(包私有的):

package server

// Exported: accessible from other packages
type Server struct {
    Addr    string   // exported field
    timeout int      // unexported field
}

// Exported method
func (s *Server) Start() error { return nil }

// Unexported helper
func (s *Server) listen() {}

main 包与 func main

main 包比较特殊——它定义一个可执行程序。main 函数是程序的入口点:

package main

import "fmt"

func main() {
    fmt.Println("Hello, Go!")
    // Program starts here and ends here
}

// All other packages are libraries — no main() needed

init() 函数

每个包可以有一个或多个 init() 函数,它们会在 main() 之前自动运行,并按照声明顺序执行:

package config

import "fmt"

var DB string

func init() {
    DB = "localhost:5432/mydb"
    fmt.Println("config package initialized")
}

// init runs once when the package is first imported
// Multiple init() functions per file/package are allowed

仅为副作用而进行的空白导入

使用空白标识符导入一个包,仅使用其 init() 产生的副作用:

package main

import (
    "database/sql"
    _ "github.com/lib/pq"  // registers PostgreSQL driver via init()
)

func main() {
    db, err := sql.Open("postgres", "host=localhost dbname=test")
    _ = db
    _ = err
}

带别名的导入

导入时重命名包,以避免名称 collision 或缩短写法:

package main

import (
    "fmt"
    gomath "math"              // alias to avoid collision
    mymath "github.com/me/math"
)

func main() {
    fmt.Println(gomath.Sqrt(16))     // 4
    fmt.Println(mymath.Add(1, 2))    // 3
}

包命名约定

Go 的包命名约定:

  • 简短、小写、使用单个单词:http、json、fmt
  • 与目录名一致:util/stringutil/ → 包 stringutil
  • 包名中不要使用下划线或 camelCase
  • 避免使用 util、common、helper 等通用名称
  • 包名是标识符的一部分:优先使用 http.Client,而不是 httplib.HTTPClient

循环导入

Go 不允许循环导入。若包 B 导入包 A,包 A 就不能再导入包 B。请将共享代码提取到第三个包中,以解决此问题:

// WRONG: A imports B, B imports A — compile error
// package a imports "myapp/b"
// package b imports "myapp/a"

// SOLUTION: extract shared types to package c
// package a imports "myapp/c"
// package b imports "myapp/c"
// No circular dependency

快速检查

在 Go 中,什么特征会使一个标识符被导出?

回顾:包

包的关键概念:

  • 每个文件都以 package name 开头
  • 大写字母 = 已导出(公开),小写字母 = 未导出(包私有)
  • 通过完整路径导入,通过简短的包名使用
  • init() 会在 main() 之前自动运行
  • 仅为副作用而使用空白导入 _ "pkg"
  • 不允许循环导入

常见问题解答

「包:组织 Go 代码」课时是免费的吗?

是的 — 「包:组织 Go 代码」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。

「包:组织 Go 代码」这节课中我会学到什么?

包声明、导入与导出名称 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「包:组织 Go 代码」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Go Academy 课中编写并运行代码吗?

能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 包:组织 Go 代码
  2. 使用 go mod 管理 Go 模块
  3. 添加外部依赖
  4. 内部包与工作区
← 返回 Go Academy