项目结构规范与 .env 管理:让 ADK Go 项目从"能跑"到"可维护"

个人项目可以随心所欲,但工程化项目必须讲究规范。在带领团队落地多个 ADK Go 生产项目后,我深刻体会到:前期多花 30 分钟建立规范,后期能节省数小时的排障和沟通成本。本章将从目录结构、敏感信息管理、多环境配置、团队协作四个维度,给出一套经过生产验证的 ADK Go 项目组织方案。

标准 ADK Go 项目结构

一个工程化的 ADK Go 项目应该长这样:

my_agent/
├── cmd/
   └── agent/
       └── main.go           # 应用程序入口(遵循 Go 标准项目布局)
├── internal/
   ├── agent/
      └── time_agent.go     # Agent 定义与配置
   ├── config/
      └── config.go         # 配置加载与校验
   └── tools/
       └── custom_tools.go   # 自定义工具集
├── pkg/
   └── utils/
       └── helpers.go        # 可复用的公共工具函数
├── .env                      # 本地环境变量(绝不提交 git)
├── .env.example              # 环境变量模板(提交 git)
├── .env.staging              # Staging 环境配置(按需)
├── .gitignore
├── go.mod
├── go.sum
├── Makefile                  # 常用命令封装
└── README.md

为什么不是单文件结构?

官方 Quickstart 为了演示简洁,把所有代码放在 agent.go 中。但在实际工程中,这种写法很快会遇到瓶颈:

  • 代码膨胀:当 Agent 数量增加到 5 个以上,单文件会超过 500 行,可读性急剧下降
  • 测试困难:单文件结构难以编写单元测试
  • 复用障碍:自定义 Tool 无法被其他项目引用
  • 职责混乱:配置、业务逻辑、启动代码耦合在一起

遵循 Go Standard Project Layout 将代码按职责分层,是长期可维护的基础。


go.mod:模块初始化与依赖管理

初始化模块

cd my_agent
go mod init github.com/yourorg/my-agent

模块路径建议使用代码托管平台的完整路径(如 github.com/yourorg/my-agent),这样便于后续被其他项目引用或发布到内部私有仓库。

依赖管理最佳实践

运行 go mod tidy 后,生成的 go.mod 大致如下:

module github.com/yourorg/my-agent

go 1.24.4

require (
    google.golang.org/adk v0.2.0
    google.golang.org/genai v0.3.0
)

生产环境经验

  1. 锁定主版本:在 go.mod 中明确指定 ADK Go 的版本,不要依赖 @latest。我们在一次版本升级中遇到过 llmagent.Config 结构体字段变更,导致编译失败。

  2. 定期审计依赖:使用 go mod graph | grep 检查间接依赖,确保没有引入已知漏洞的库:

go list -m -versions google.golang.org/adk  # 查看可用版本
go mod why google.golang.org/genai           # 查看为什么依赖这个包
  1. Vendor 策略:对于需要离线构建或长期存档的项目,考虑使用 vendor 模式:
go mod vendor  # 将所有依赖复制到 vendor/ 目录
# 后续构建时加上 -mod=vendor 使用本地依赖
go build -mod=vendor ./cmd/agent

.env 与 .env.example:敏感信息分离策略

这是所有项目中最重要的规范,没有之一。API Key、数据库密码、私钥等敏感信息一旦泄露,后果可能是灾难性的。

核心原则

  • .env:存放真实值,绝不提交到版本控制
  • .env.example:存放示例值和说明,必须提交到版本控制
  • .env.*:按环境区分的配置文件,根据安全策略决定是否提交

.env.example 模板设计

一个好的模板不仅要列出变量名,还要说明每个变量的用途、格式要求和获取方式:

# ============================================
# ADK Go Agent 环境变量配置模板
# 复制本文件为 .env 并填入真实值
# ============================================

# Google Gemini API Key(必填)
# 获取地址:https://aistudio.google.com/app/apikey
# 注意:每个 Key 有配额限制,生产环境建议使用 Key Pool
export GOOGLE_API_KEY="your-api-key-here"

# 模型选择(可选,默认 gemini-2.0-flash)
# 可选值:gemini-2.0-flash, gemini-2.0-pro, gemini-2.0-flash-exp
# 开发环境建议用 flash(快且便宜),生产复杂任务可切换到 pro
export GEMINI_MODEL="gemini-2.0-flash"

# 日志级别(可选,默认 info)
# 可选值:debug, info, warn, error
export LOG_LEVEL="info"

# 代理配置(中国大陆等受限网络环境必填)
# 格式:http://host:port 或 socks5://host:port
export HTTPS_PROXY=""

# ADK 运行模式(可选,默认 cli)
# 可选值:cli, web
export ADK_MODE="cli"

# Web 模式端口(可选,默认 8080)
export ADK_PORT="8080"

配置加载代码

internal/config/config.go 中封装配置加载逻辑:

package config

import (
	"fmt"
	"os"
	"strconv"
)

// Config 保存应用的所有配置项
type Config struct {
	APIKey     string
	Model      string
	LogLevel   string
	Proxy      string
	Mode       string
	Port       int
}

// Load 从环境变量加载配置,并进行必要的校验
func Load() (*Config, error) {
	apiKey := os.Getenv("GOOGLE_API_KEY")
	if apiKey == "" {
		return nil, fmt.Errorf("GOOGLE_API_KEY is required. " +
			"Copy .env.example to .env and fill in your API key")
	}

	port, _ := strconv.Atoi(getEnv("ADK_PORT", "8080"))

	return &Config{
		APIKey:   apiKey,
		Model:    getEnv("GEMINI_MODEL", "gemini-2.0-flash"),
		LogLevel: getEnv("LOG_LEVEL", "info"),
		Proxy:    os.Getenv("HTTPS_PROXY"),
		Mode:     getEnv("ADK_MODE", "cli"),
		Port:     port,
	}, nil
}

func getEnv(key, defaultValue string) string {
	if v := os.Getenv(key); v != "" {
		return v
	}
	return defaultValue
}

.gitignore 配置

# ============================================
# 敏感信息(绝对不要提交)
# ============================================
.env
.env.local
.env.*.local
*.pem
*.key

# ============================================
# Go 构建产物
# ============================================
bin/
dist/
*.exe
*.dll
*.so
*.dylib

# ============================================
# 依赖管理(go.sum 建议提交,确保构建一致性)
# ============================================
# 注意:go.sum 包含依赖校验和,提交它可避免"在我机器上能跑"的问题
# 如果你坚持不提交 go.sum,取消下面这行的注释
# go.sum

# ============================================
# IDE 与编辑器
# ============================================
.idea/
.vscode/
*.swp
*.swo
*~

# ============================================
# 操作系统
# ============================================
.DS_Store
Thumbs.db

多环境配置:开发 / 测试 / 生产

实际项目中,不同环境往往需要不同的配置:开发环境用轻量级模型、开启 Debug 日志;生产环境用更强的模型、只记录 Error。

环境文件组织

my_agent/
├── .env                 # 本地开发(不提交 git,每个开发者独立)
├── .env.example         # 共享模板(提交 git)
├── .env.staging         # 预发布环境(可选,可提交 git 若不含敏感信息)
├── .env.production      # 生产环境(不提交 git,由 CI/CD 或 Secret Manager 注入)

环境切换脚本

Makefile 中封装环境切换逻辑:

.PHONY: run run-staging run-prod dev staging prod

# 默认运行开发环境
dev:
	@test -f .env || (echo "Error: .env not found. Run: cp .env.example .env" && exit 1)
	@source .env && go run ./cmd/agent

# Staging 环境
staging:
	@source .env.staging && go run ./cmd/agent

# 生产环境(仅用于验证配置,正式部署应使用构建产物)
prod:
	@source .env.production && go run ./cmd/agent

# 构建二进制
build:
	@go build -o bin/agent ./cmd/agent

# 运行测试
test:
	@go test -v ./...

使用方式:

make dev      # 开发环境
make staging  # 预发布环境
make build    # 编译二进制到 bin/agent

代码中的环境感知

package main

import (
	"log"
	"os"

	"my_agent/internal/config"
)

func main() {
	cfg, err := config.Load()
	if err != nil {
		log.Fatalf("Configuration error: %v", err)
	}

	// 根据环境调整行为
	if cfg.Mode == "development" {
		log.Println("Running in DEVELOPMENT mode")
		// 开发环境特定逻辑:详细日志、模拟数据等
	}

	// ... 初始化 Agent
}

README.md:团队知识沉淀

README 不是写给机器的,是写给人的。一个好的 README 能让新成员在 10 分钟内跑起项目。

推荐结构

# My ADK Go Agent

## 项目简介

基于 Google ADK Go 构建的智能助手,支持时间查询、天气查询等功能。

## 前置要求

- Go 1.24.4+
- Google API Key([获取方式](https://aistudio.google.com/app/apikey))
- Make(可选,用于快捷命令)

## 快速开始

1. 克隆项目
2. 复制环境变量模板:`cp .env.example .env`,填入真实值
3. 安装依赖:`go mod tidy`
4. 运行:`make dev``source .env && go run ./cmd/agent`

## 环境变量说明

| 变量 | 说明 | 必填 | 默认值 |
|------|------|------|--------|
| GOOGLE_API_KEY | Google Gemini API Key | 是 | - |
| GEMINI_MODEL | 模型名称 | 否 | gemini-2.0-flash |
| LOG_LEVEL | 日志级别 | 否 | info |
| HTTPS_PROXY | 代理地址 | 否 | - |

## 项目结构

cmd/agent/ # 主入口 internal/ # 私有代码 agent/ # Agent 定义 config/ # 配置管理 tools/ # 自定义工具 pkg/utils/ # 公共工具


## 常用命令

| 命令 | 说明 |
|------|------|
| `make dev` | 开发环境运行 |
| `make build` | 编译二进制 |
| `make test` | 运行测试 |

## 部署说明

生产环境通过 GitHub Actions 自动构建并部署到 [你的平台]。
敏感配置通过 [Secret Manager / K8s Secrets] 注入,不存储在代码仓库中。

团队协作规范

Git 分支策略

推荐采用简化版 Git Flow:

main                    # 生产分支,永远可部署
├── develop             # 开发分支,功能集成
   ├── feat/search-tool      # 功能分支
   ├── feat/weather-agent
   └── fix/api-timeout
└── hotfix/v0.1.1       # 紧急修复

分支命名规范

  • feat/short-description:新功能
  • fix/short-description:Bug 修复
  • docs/short-description:文档更新
  • refactor/short-description:代码重构

Commit Message 规范

使用 Conventional Commits 规范,便于自动生成 CHANGELOG:

feat(agent): 添加天气查询 Agent
fix(config): 修复 .env 未加载时 panic 的问题
docs(readme): 更新部署说明
refactor(tools): 提取通用 HTTP 客户端
chore(deps): 升级 ADK Go  v0.2.1

Code Review 检查清单

每次合并前,Review 者应确认:

  • .env 等敏感文件未被提交
  • 新增依赖是否必要
  • 错误处理是否完善
  • 配置项是否已更新 .env.example
  • 是否包含测试(如有测试框架)

常见问题与深度排障

Q:.env 不小心提交到 git 了怎么办?

立即执行以下操作

# 1. 从 git 历史中彻底删除(重写历史)
git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch .env' \
  --prune-empty --tag-name-filter cat -- --all

# 2. 强制推送到远程(注意:这会重写远程历史,团队需协调)
git push origin --force --all

# 3. 在 .gitignore 中添加 .env
echo ".env" >> .gitignore

# 4. 立即撤销已泄露的 API Key
# 登录 Google AI Studio,删除旧 Key 并生成新 Key

教训:预防胜于治疗。建议在仓库中配置 git-secrets pre-commit 钩子,在提交前自动检测敏感信息。

Q:团队成员 GOPROXY 配置不同,导致 go mod tidy 结果不一致

解决方案:在项目根目录创建 .gomodproxy 文件(或写入 README),统一代理配置:

# 统一使用 goproxy.cn
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=sum.golang.org

更彻底的做法是在 CI 中固定代理,确保构建一致性。

Q:多个 Agent 项目需要共享自定义工具,怎么组织?

方案 A:内部工具库(推荐)

创建独立的 Go Module 存放共享工具:

my-org/
├── adk-tools/          # 独立仓库
   ├── go.mod
   ├── search/
      └── google_search.go
   └── weather/
       └── weather_api.go
├── agent-a/
└── agent-b/

在 Agent 项目的 go.mod 中引用:

require github.com/my-org/adk-tools v1.0.0

方案 B:Mono Repo(适合小团队)

如果工具代码量不大,可以使用 Go Workspace:

# 在父目录初始化 workspace
go work init ./adk-tools ./agent-a ./agent-b

这样所有模块共享同一个 go.work 文件,本地开发时修改工具代码立即生效。


下一步

项目结构规范建立好后,你的代码库已经具备了工程化的基础。接下来进入模块 2:快速入门。我们将从零构建一个完整的 Hello World Agent,深入理解 Model、Tool、Instruction 三要素的协作机制,并学习如何在代码中处理边界情况和错误场景。

ADK Go 安装与快速验证 | Agent 核心概念 →


想跟着学更多 Go ADK 实战?关注「全栈之巅-梦兽编程」公众号,每周更新 Go / AI 编程实战干货。

也欢迎了解 梦兽编程 AI 编程助手服务 ,帮你把 AI 编程工具用到生产环境。