Go 版本安装

下载地址:https://go.dev/dl/

注意:MacOS 选择 go1.24.1.darwin-arm64.pkg 类型的安装包。

目录结构

my-project/
├── cmd/                # 可执行文件入口
│   └── myapp/          # 主程序入口目录
│       └── main.go     # main函数
├── internal/           # 私有代码(禁止外部引用)
│   ├── config/         # 配置处理
│   ├── controller/     # 控制层(HTTP handlers)
│   ├── service/        # 业务逻辑层
│   └── repository/     # 数据访问层
├── pkg/                # 公共库代码(允许外部引用)
│   ├── utils/          # 通用工具函数
│   └── middleware/     # HTTP中间件
├── api/                # API定义文件
│   ├── rest/           # REST API规范(OpenAPI/Swagger)
│   └── rpc/            # gRPC proto文件
├── configs/            # 配置文件模板
├── test/               # 集成测试和测试数据
├── scripts/            # 构建/部署脚本
├── deployments/        # 部署配置(Docker/K8s)
├── docs/               # 文档
├── go.mod              # 模块定义
└── go.sum              # 依赖校验

环境变量配置

# .bashrc

# golang
export PATH=$PATH:/usr/local/go/bin
export GOBIN=$HOME/go/bin
export PATH=$GOBIN:$PATH

# @refer https://learnku.com/go/t/39086#0b3da8
export GO111MODULE=on

# 进行设置 go proxy 和 go sumdb
export GOPROXY="xxx"
export GOPRIVATE=""
export GOSUMDB="xxx"

GoLang IDE

GoLand

TODO

VSCode

启用 gopls

可以在工程的 VSCode settings.json 配置中设置开启 gopls 服务,即,"go.useLanguageServer": true

{
    "editor.insertSpaces": true,
    "editor.tabSize": 4,
    "files.encoding": "utf8",
    "files.eol": "\n",
    "gopls": {
    },
    "go.useLanguageServer": true,
    "go.languageServerFlags": ["-remote=auto", "-logfile=auto", "-debug=:0", "-rpc.trace",],
    "[go]": {
        "editor.formatOnSave": true
    },
}

VSCode 第一次加载时会根据 settings.json 配置下载和启动 gopls 服务。

go1

首先安装 Go for Visual Studio Code 扩展,该插件最初是微软维护的,目前已经交给 Go Team 维护。The VS Code Go extension provides rich language support for the Go programming language.

当在 VSCode 中启用 Use Language Server 时,它会启动一个 gopls 进程,即它就是 LSP 的实现,VSCode 通过 vscode-go 和 gopls 通讯。

打开 VSCode 配置界面,定位到 Extensions -> Go 中,找到 Use Language Server,勾选上。

对应的配置是:”Go.useLanguageServer”: true。如果本地没有安装 gopls,会提示安装。如果没有提示,可以通过 Command Palette 命令窗口,搜索 Go: Install/Update Tools 命令并选择 gopls 进行安装。当 gopls 有更新时,VSCode 会自动更新。

关于 gopls 的配置:https://github.com/golang/tools/blob/master/gopls/doc/settings.md

默认情况下,每次启动一个 VSCode 窗口,gopls 进程就会多一个。因为 gopls 需要维护大量的缓存,方便对编辑的源代码进行分析。因此,这种工作模式会导致 gopls 占用太多资源。为了解决此类问题,gopls 支持一种新的模式,即启动一个单一的、持久的、共享的 gopls “守护进程” 负责管理所有 gopls 会话。在这种模式下,编辑器的每一个窗口依然会启动一个新的 gopls,不过这个 gopls 只是充当转发器,负责将 LSP 转发到那个共享的 gopls 实例,并记录相关指标、日志和 rpc 跟踪,因此这个 gopls 占用资源很少。

要使用共享 gopls 实例,必须有一个守护进程。可以手动启动,不过更方便的是让 gopls 转发器进程根据需要启动共享守护进程。具体来说是使用 -remote=true 这个 flag。这将导致该进程在需要时自动启动 gopls 守护进程,连接到它并转发 LSP

注意:在没有连接客户端的情况下,共享 gopls 进程将在一分钟后自动关闭。关于共享 gopls 更多的内容,可以查看 Gopls: Running as a daemon 文档。

$ gopls -h

gopls is a Go language server.

It is typically used with an editor to provide language features. When no
command is specified, gopls will default to the 'serve' command. The language
features can also be accessed via the gopls command-line interface.

For documentation of all its features, see:

   https://github.com/golang/tools/blob/master/gopls/doc/features

Usage:
  gopls help [<subject>]

Command:

Main
  serve             run a server for Go code using the Language Server Protocol
  version           print the gopls version information
  bug               report a bug in gopls
  help              print usage information for subcommands
  api-json          print JSON describing gopls API
  licenses          print licenses of included software

Features
  call_hierarchy    display selected identifier's call hierarchy
  check             show diagnostic results for the specified file
  codeaction        list or execute code actions
  codelens          List or execute code lenses for a file
  definition        show declaration of selected identifier
  execute           Execute a gopls custom LSP command
  fix               apply suggested fixes (obsolete)
  folding_ranges    display selected file's folding ranges
  format            format the code according to the go standard
  highlight         display selected identifier's highlights
  implementation    display selected identifier's implementation
  imports           updates import statements
  remote            interact with the gopls daemon
  inspect           interact with the gopls daemon (deprecated: use 'remote')
  links             list links in a file
  prepare_rename    test validity of a rename operation at location
  references        display selected identifier's references
  rename            rename selected identifier
  semtok            show semantic tokens for the specified file
  signature         display selected identifier's signature
  stats             print workspace statistics
  symbols           display selected file's symbols
  workspace_symbol  search symbols in workspace

flags:
  -debug=string
        serve debug information on the supplied address
  -listen=string
        address on which to listen for remote connections. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. Otherwise, TCP is used.
  -listen.timeout=duration
        when used with -listen, shut down the server when there are no connected clients for this duration
  -logfile=string
        filename to log to. if value is "auto", then logging to a default output file is enabled
  -mode=string
        no effect
  -ocagent=string
        the address of the ocagent (e.g. http://localhost:55678), or off (default "off")
  -port=int
        port on which to run gopls for debugging purposes
  -profile.alloc=string
        write alloc profile to this file
  -profile.block=string
        write block profile to this file
  -profile.cpu=string
        write CPU profile to this file
  -profile.mem=string
        write memory profile to this file
  -profile.trace=string
        write trace log to this file
  -remote=string
        forward all commands to a remote lsp specified by this flag. With no special prefix, this is assumed to be a TCP address. If prefixed by 'unix;', the subsequent address is assumed to be a unix domain socket. If 'auto', or prefixed by 'auto;', the remote address is automatically resolved based on the executing environment.
  -remote.debug=string
        when used with -remote=auto, the -debug value used to start the daemon
  -remote.listen.timeout=duration
        when used with -remote=auto, the -listen.timeout value used to start the daemon (default 1m0s)
  -remote.logfile=string
        when used with -remote=auto, the -logfile value used to start the daemon
  -rpc.trace
        print the full rpc trace in lsp inspector format
  -v,-verbose
        verbose output
  -vv,-veryverbose
        very verbose output

Tools

gopkgs

这是 go list all 命令的替代者,用于列出可用的 Go 包,速度比 go list all 更快。

# Go 1.12+
go install github.com/uudashr/gopkgs/v2/cmd/gopkgs@latest

go-outline

将 Go 源码中的声明提取为 JSON 的工具。

go get -u github.com/lukehoban/go-outline

goimports

自动导入缺失或移除多余的 import。同时还兼带有 gofmt 的功能。

golangci-lint

golangci-lint is a Go linters aggregator.

# binary will be $(go env GOPATH)/bin/golangci-lint
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.52.2

golangci-lint --version

delve

专为 Go 的调试器。

最佳实践

  • 分层架构
    • 采用清晰的层级分离(Controller-Service-Repository)
    • 使用依赖注入模式(推荐 Wire)
    • 遵循整洁架构原则
  • 配置管理
// 推荐使用 Viper + 环境变量
func InitConfig() {
    viper.AutomaticEnv()
    viper.SetConfigFile(".env")
    if err := viper.ReadInConfig(); err != nil {
        log.Fatal("Error reading config: ", err)
    }
}
  • 错误处理
    • 使用errors.Wrap保留堆栈信息
    • 定义可导出错误类型
var ErrRecordNotFound = errors.New("record not found")
  • 日志规范
// 推荐使用 zap 或 logrus
logger, _ := zap.NewProduction()
defer logger.Sync()
logger.Info("Server started",
    zap.String("port", cfg.Port),
    zap.Int("workers", cfg.Workers))
  • 测试策略
    • 单元测试:与被测试文件同目录(_test.go
    • 集成测试:单独 test 目录
    • 使用 testify/assert 做断言
    • 使用 gomock 生成测试 mock
  • 性能优化
    • 使用 pprof 进行性能分析
    • 避免频繁内存分配(sync.Pool 管理对象池)
    • 使用 benchmark 测试关键路径
  • 安全实践
    • 启用-race进行竞态检测
    • 使用crypto/rand生成随机数
    • 对用户输入严格校验(推荐 validator
  • 持续集成
# 示例 GitHub Actions 配置
name: CI
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-go@v2
        with: { go-version: '1.21' }
      - run: go test -race -coverprofile=coverage.txt ./...
  • 文档生成
# 安装 swag 工具
go install github.com/swaggo/swag/cmd/swag@latest

# 生成 API 文档
swag init -g cmd/myapp/main.go
  • 代码质量
    • 使用golangci-lint进行静态检查
    • 设置pre-commit钩子
# .pre-commit-config.yaml
repos:
- repo: https://github.com/golangci/golangci-lint
  rev: v1.55.2
  hooks:
    - id: golangci-lint
  • 微服务架构
    • 使用go-kitgRPC构建服务
    • 添加api目录存放proto文件
    • 实现健康检查端点
  • 分布式追踪
// 使用 OpenTelemetry
provider := otel.GetTracerProvider()
tracer := provider.Tracer("service-name")
ctx, span := tracer.Start(ctx, "operation-name")
defer span.End()
  • 错误监控
    • 集成SentryDataDog
sentry.Init(sentry.ClientOptions{
    Dsn: "your-dsn",
    Release: "myapp@v1.0.0",
})
  • 代码生成
    • 使用go:generate指令
//go:generate mockgen -source=repository.go -destination=mock_repository.go -package=repository
  • 性能关键路径
    • 使用cgo优化计算密集型任务
    • 考虑使用汇编优化(math/big等标准库做法)

代码工程

初始化模块

go mod init my-project
go mod tidy

单元测试

# 安装测试依赖
go install github.com/stretchr/testify@v1.9.0
go install github.com/stretchr/testify/mock@v1.9.0

# 执行测试
go test -v ./...

第三方组件

配置

https://github.com/spf13/viper

日志

  • https://github.com/uber-go/zap
  • https://github.com/uber-go/zap/blob/master/FAQ.md

简单示例:

// 高性能模式(零内存分配)
logger := zap.NewExample()
defer logger.Sync()
logger.Debug("This is a debug message")

// 兼容模式(类似 fmt.Printf)
sugar := logger.Sugar()
sugar.Debugf("Formatted message: %s", "value")

在其他 package 中使用 zap 的全局实例(推荐):

import "go.uber.org/zap"

func example() {
	zap.L().Info("This is a log using global instance")
}

Gin (高性能 HTTP Web 框架)

Gin is a web framework written in Go. It features a martini-like API with performance that is up to 40 times faster thanks to httprouter. If you need performance and good productivity, you will love Gin.

Tips

生成 vendor 目录 (方便查看第三方源码)

# 在 VS Code 终端运行
go mod vendor

清理旧依赖缓存

go clean -cache
go clean -modcache

GoLang GOOS and GOARCH

获取当前环境变量信息:

go env GOOS
go env GOARCH

All of the following information is based on go version go1.17.1 darwin/amd64.

GOOS Values

GOOS Out of the Box
aix
android
darwin
dragonfly
freebsd
hurd  
illumos
ios
js
linux
nacl  
netbsd
openbsd
plan9
solaris
windows
zos  

Note: “Out of the box” means the GOOS is supported out of the box, i.e. the stocked go command can build the source code without the help of a C compiler, etc.

Note: The full list is based on https://github.com/golang/go/blob/master/src/go/build/syslist.go. The “out of the box” information is based on the result of 2-make1.sh below.

GOARCH Values

GOARCH Out of the Box 32-bit 64-bit
386  
amd64  
amd64p32    
arm  
arm64  
arm64be    
armbe    
loong64    
mips  
mips64  
mips64le  
mips64p32    
mips64p32le    
mipsle  
ppc    
ppc64  
ppc64le  
riscv    
riscv64  
s390    
s390x  
sparc    
sparc64    
wasm  

All 32-bit GOARCH values:

"386", "amd64p32", "arm", "armbe", "mips", "mips64p32", "mips64p32le", "mipsle", "ppc", "riscv", "s390", "sparc"

All 64-bit GOARCH values:

"amd64", "arm64", "arm64be", "loong64", "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "sparc64", "wasm"

Note: “Out of the box” means the GOARCH is supported out of the box, i.e. the stocked go command can build the source code without the help of a C compiler, etc.

Note: The full list is based on https://github.com/golang/go/blob/master/src/go/build/syslist.go. The “out of the box” information is based on the result of 2-make1.sh below. The “32-bit/64-bit” information is based on the result of 4-make2.sh below and https://golang.org/doc/install/source.

代码工具

golangci-lint

golangci-lint is a fast Go linters runner. It runs linters in parallel, uses caching, supports YAML configuration, integrates with all major IDEs, and includes over a hundred linters.

# binary will be $(go env GOPATH)/bin/golangci-lint
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.7

golangci-lint --version

jq

jq is a lightweight and flexible command-line JSON processor akin to sed, awk, grep, and friends for JSON data. It’s written in portable C and has zero runtime dependencies, allowing you to easily slice, filter, map, and transform structured data.

https://github.com/jqlang/jq/releases