0Pricing
Go Academy · 课时

内部包与工作区

internal/、replace 指令与 go work

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

internal/ 目录

internal/ 目录中的包只能由父目录树中的代码导入。这会强制实现包封装:

// Project structure:
// myapp/
//   main.go
//   internal/
//     auth/auth.go      <- can only be imported by myapp/
//     db/db.go          <- can only be imported by myapp/
//   api/
//     handlers.go       <- can import myapp/internal/auth

// External package CANNOT do:
// import "myapp/internal/auth"  <- compile error

使用 internal/ 包

同一模块中位于 internal/ 目录上层的代码,可以自由导入内部包:

// myapp/api/handlers.go
package api

import (
    "myapp/internal/auth"
    "myapp/internal/db"
)

func GetUser(id int) (*db.User, error) {
    if !auth.IsValid() {
        return nil, auth.ErrUnauthorized
    }
    return db.FindUser(id)
}

为什么使用 internal/

采用 internal/ 约定的好处:

  • 防止其他模块依赖实现细节
  • 可以自由重构,而不会破坏外部调用方
  • 清晰表明:这不是公开 API 的一部分
  • 标准 Go 工具会在编译时强制执行此限制

Go 工作区——go work

Go 1.18 引入了工作区,可以在不使用 replace 指令的情况下,同时处理多个本地模块:

# Create a workspace in parent directory:
go work init ./myapp ./mylib

# Creates go.work:
# go 1.21
# use (
#     ./myapp
#     ./mylib
# )

# Now myapp can import mylib without replace directives

go work sync

使用 go work sync 同步工作区依赖项:

# go.work file:
go 1.21

use (
    ./api
    ./worker
    ./shared
)

# Sync all module dependencies:
go work sync

# Build across all workspace modules:
go build ./...

# Test across all workspace modules:
go test ./...

工作区与 replace 指令

本地多模块开发的两种方式比较:

// BEFORE workspaces (cumbersome):
// go.mod in myapp:
// replace github.com/me/mylib => ../mylib
// Must remove before publishing!

// WITH workspaces (cleaner):
// go.work at root:
// use (./myapp ./mylib)
// go.mod files stay clean — go.work is gitignored

工作区的使用场景

适合使用 Go 工作区的情况:

  • 同时开发一个库及其使用者
  • 多个相互引用模块组成的单一代码库
  • 在发布共享模块前测试其更改
  • 在应用程序旁边同时开发某个依赖项的分支

go work add 和 go work use

使用 go work 子命令管理工作区条目:

# Add a module to the workspace
go work use ./newservice

# Remove a module from workspace
go work use -r ./oldservice

# Edit go.work directly (opens $EDITOR):
go work edit

# go.work should usually be gitignored:
echo "go.work" >> .gitignore
echo "go.work.sum" >> .gitignore

内部包与工作区的结合

在单一代码库中,内部包和工作区可以自然地结合使用:

// Monorepo structure:
// services/
//   go.work
//   auth-service/
//     internal/tokens/   <- private to auth-service
//   order-service/
//     internal/pricing/  <- private to order-service
//   shared/
//     models/            <- shared across services

// go.work:
// use (./auth-service ./order-service ./shared)

包组织的最佳实践

Go 项目布局建议:

  • 小型项目使用扁平的包结构——避免过早组织
  • 对于不打算供外部使用的实现细节,请使用 internal/
  • 将 CLI 主包放在 cmd/appname/ 下
  • 多模块代码库使用工作区,但请将 go.work 加入 gitignore
  • 避免过深的嵌套——包最多嵌套 3 到 4 层

快速检查

谁可以导入 internal/ 目录中的包?

回顾:内部包与工作区

总结:

  • internal/ 将导入限制在父目录树内——由编译器强制执行
  • 使用 internal/ 向外部使用者隐藏实现细节
  • go work init 创建用于多模块本地开发的工作区
  • 工作区可以替代本地开发中的 replace 指令
  • 将 go.work 和 go.work.sum 加入 Git 忽略列表

常见问题解答

「内部包与工作区」课时是免费的吗?

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

「内部包与工作区」这节课中我会学到什么?

internal/、replace 指令与 go work 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

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

「内部包与工作区」课时需要多长时间?

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

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

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

此课程中的所有课时

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