惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
T
Threatpost
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tenable Blog
AWS News Blog
AWS News Blog
Know Your Adversary
Know Your Adversary
TaoSecurity Blog
TaoSecurity Blog
P
Palo Alto Networks Blog
Spread Privacy
Spread Privacy
I
Intezer
Security Latest
Security Latest
The Last Watchdog
The Last Watchdog
Google DeepMind News
Google DeepMind News
Help Net Security
Help Net Security
Cyberwarzone
Cyberwarzone
N
News and Events Feed by Topic
O
OpenAI News
A
Arctic Wolf
S
Secure Thoughts
Attack and Defense Labs
Attack and Defense Labs
N
News and Events Feed by Topic
M
MIT News - Artificial intelligence
F
Full Disclosure
P
Privacy International News Feed
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
H
Hacker News: Front Page
aimingoo的专栏
aimingoo的专栏
S
Security @ Cisco Blogs
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Apple Machine Learning Research
Apple Machine Learning Research
Engineering at Meta
Engineering at Meta
Cloudbric
Cloudbric
大猫的无限游戏
大猫的无限游戏
Google Online Security Blog
Google Online Security Blog
Recent Announcements
Recent Announcements
H
Help Net Security
量子位
V
V2EX
美团技术团队
G
Google Developers Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Schneier on Security
V2EX - 技术
V2EX - 技术
D
Docker
博客园 - 【当耐特】
Project Zero
Project Zero
博客园 - 司徒正美

博客园 - 曦远Code

给热水器装上“电量显示”:用 Shelly Gen4 脚本实现零改装水量预测 StarBlog番外(5) 从1.6到1.10,基于Avalonia AOT 开发的 Publisher 半年进化之路 你的显卡能跑多少算子?用 55 个检查项,给 PyTorch GPU 环境做一次冒烟测试 ROCm on Windows 性能排查:RX 6650 XT 跑 PyTorch,为什么加速不明显? lighthouse-fw:一个管理腾讯云轻量服务器防火墙的终端工具 用本地大模型驱动中文输入法,我做了一个实验性的项目 Spark.NET:一个试图把 Django / Rails 式开发体验带回 .NET 世界的全栈 Web 框架。 Zed AI 白嫖免费模型,搭配 DeepSeek v4,玩转 Agent 编程技巧 2026年AI编程工具横评:Cursor、Codex、Claude Code、Zed、Windsurf 后 Django 时代:SQLAlchemy 2.0、Tortoise 与 Piccolo 三大异步 ORM 选型指南 Python网络请求库,从 requests 到 httpx 浅谈次世代代码编辑器 Zed:Rust 原生性能、GPU 渲染 现代 Python 程序优雅处理日期时间的避坑指南 你的SSH密钥可能已经过期了 是谁 2026 年还在用 Sublime Text 写代码? 什么年代了怎么还在用bash啊?现代化shell开箱体验: fish, nu, elvish 别再手动复制SSH公钥了,Linux服务器一键从GitHub快速导入公钥 2026年的Linux桌面环境选择,哪些适合Debian服务器? 在 Windows 11 上使用 Hyper-V 虚拟机准备安装OpenClaw C# 扩展方法只会写 this 吗?C# 14 新语法直接把扩展方法玩出了花 经历分享,发现挖矿木马后,服务器快速备份与重装(腾讯云平台) Coolify: Vercel 的开源版私有化部署平替版 分享一些2026年有意思的现代化Django生态组件 实测 Django 6.0:模版片段、后台任务、CSP 安全,三大特性体验报告 当人人都能用 AI 写代码时,我为什么选择重回 Django? 打包ROCm环境的相关Wheel方便后续使用 从挖矿木马入侵到 Docker Rootless 加固,我的服务器安全复盘 AMD显卡也能畅玩AI画图!ROCm+ComfyUI部署全指南
当 CGO 遇见 Zig:一种更优雅的折腾方式,对比 GCC 后端
曦远Code · 2026-04-28 · via 博客园 - 曦远Code

前言

我最近在 Windows 环境下构建一个涉及数据库(SQLite)和音频处理的 Go 项目时,遇到了一个预料之中的报错:

cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in %PATH%

这是因为 Go 的 cgo 机制需要调用外部的 C 编译器来处理 C 代码。Windows 默认不包含 GCC 环境,所以我们需要手动配置一套 C 工具链。

使用 Scoop 快速安装 GCC

对于习惯使用命令行工具的开发者,不建议去手动下载安装包配置环境变量。通过 Scoop 可以非常快速地解决这个问题:

scoop install gcc

安装完成后,在终端运行 gcc --version。如果能看到版本输出,说明环境变量已经由 Scoop 自动配置完成。

此时,如果运行 go build,项目通常已经可以正常编译。

使用 Zig 代替 GCC

虽然 GCC 能解决问题,但在进一步调研中,我发现使用 Zig 作为 C 编译器是更高效的选择。Zig 虽然是一门编程语言,但它的编译器(zig cc)可以作为一个完整的 C/C++ 编译器前端使用。

为什么选择 Zig?

  • 安装更轻量:通过 scoop install zig 即可获得一个单文件的编译器,不需要像 MinGW 那样管理复杂的文件夹结构。
  • 内置标准库:Zig 内置了多种平台的 libc 源码,编译时不需要依赖宿主机的系统库。
  • 静态链接优势:使用 Zig 编译出的二进制文件在处理静态链接时更稳定,能减少生成的 .exe 文件对外部 .dll 的依赖。
  • 原生支持交叉编译:这是 Zig 最强的特性。你可以在 Windows 上直接编译出适配 Linux 或 macOS 的 cgo 程序,只需指定 -target 参数,而不需要配置复杂的交叉编译工具链。

安装 Zig

一样使用 scoop 即可安装

scoop install zig

配置 Go 调用 Zig 编译器

如果你已经安装了 Zig,可以通过以下步骤让 Go 默认使用它:

启用 CGO

go env -w CGO_ENABLED=1

指定 C/C++ 编译器

将 Go 环境变量中的 CCCXX 指向 Zig:

go env -w CC="zig cc"
go env -w CXX="zig c++"

针对特定平台编译(示例)

如果你需要为 Linux 平台编译:

$env:GOOS="linux"
$env:GOARCH="amd64"
$env:CC="zig cc -target x86_64-linux-gnu"
go build

测试一下

为了测试 cgo 编译,我让大模型爷爷帮忙写了一段字符串逆序的代码,这个例子涵盖了 CGO 的核心流程:C 代码定义逻辑、Go 代码通过 CGO 调用、以及数据在 Go 和 C 之间的传递。

创建文件 main.go

package main

/*
// 使用 Zig 的编译器驱动
#cgo LDFLAGS: -s -w

#include <stdlib.h>
#include <string.h>

// 这是一个简单的 C 函数,用于反转字符串
void reverse_string(char* str) {
    int len = strlen(str);
    for (int i = 0; i < len / 2; i++) {
        char temp = str[i];
        str[i] = str[len - 1 - i];
        str[len - 1 - i] = temp;
    }
}
*/
import "C"
import (
	"fmt"
	"unsafe"
)

func main() {
	input := "Hello from Zig + CGO!"
	fmt.Printf("Original: %s\n", input)

	// 将 Go 字符串转换为 C 字符串(会在堆上分配内存)
	cStr := C.CString(input)
	// 必须手动释放 C 内存
	defer C.free(unsafe.Pointer(cStr))

	// 调用 C 函数
	C.reverse_string(cStr)

	// 将修改后的 C 字符串转回 Go 字符串
	output := C.GoString(cStr)
	fmt.Printf("Reversed: %s\n", output)
}

本地编译

先用 gcc 测试

$env:CGO_ENABLED="1"
go build main.go

再用 zig 测试

$env:CGO_ENABLED="1"
$env:CC="zig cc"
go build main.go

注意

这里有一个小坑

Go 在 1.9.4 版本后引入了安全检查机制,默认会拦截一些它认为“不安全”的 CGO 标志(Flags)

-s-w 是常用的缩减体积标志,但默认会被拦截

所以需要添加一个环境变量来允许

$env:CGO_LDFLAGS_ALLOW="-s|-w"

也可以把 C 语言代码独立出来

创建 hello.h

void reverse_string(char* str);

创建 hello.c

#include <string.h>
void reverse_string(char* str) {
    int len = strlen(str);
    for (int i = 0; i < len / 2; i++) {
        char temp = str[i];
        str[i] = str[len - 1 - i];
        str[len - 1 - i] = temp;
    }
}

修改 main.go

package main

/*
#include "hello.h"
*/
import "C"
import (
    "fmt"
    "unsafe"
)

func main() {
    s := C.CString("Zig is awesome")
    defer C.free(unsafe.Pointer(s))
    C.reverse_string(s)
    fmt.Println(C.GoString(s))
}

把代码抽离到 .c 文件后,CGO 会自动寻找同目录下的 C 文件并交给 CC(即 zig cc)处理。通常不需要手动在 main.go 里写 LDFLAGS,这样不仅代码更整洁,也完美避开了 Go 的标志检查机制。

性能对比

虽然 zig 很美好,不过我又让大模型爷爷帮忙写了一个脚本,测试不同后端的编译速度和产物的执行速度。

结果发现……

维度 GCC (15.2) Zig (0.15.2) 差距 / 结论
编译耗时 (Avg) 6.67 秒 16.40 秒 Zig 慢了 1.4 倍。LLVM 架构较重且跨平台兼容层解析耗时。
运行耗时 (Avg) 18.54 毫秒 30.83 毫秒 Zig 慢了约 66%。受冷启动延迟和 CGO 调用开销影响。
首跑最大延迟 25.30 毫秒 483.68 毫秒 离谱! Zig 产物疑似触发 Windows Defender 扫描。
运行稳定性 (StdDev) 1.34 ms 45.54 ms GCC 极稳;Zig 波动剧烈(受冷启动极端值拉低)。
环境依赖 复杂 (需安装 MinGW/MSYS2) 极简 (单文件,无依赖) Zig 的核心优势所在。

注:Zig 的首跑延迟(483ms)通常只发生在该二进制文件第一次被系统执行时。如果你将 app_zig.exe 加入 Windows Defender 白名单,它的中位数运行速度会稳定在 26ms 左右,虽然仍略逊于 GCC,但已在工程可接受范围内。

结论

不要盲目迷信 Zig 的性能优化。

虽然 Zig 被誉为现代 C 语言的挑战者,但在 Windows 平台的 CGO 场景下,GCC 依然是本地性能和编译速度的王者

那为什么还要折腾 Zig?

因为在 Windows 上配置 GCC 环境简直是新手的噩梦。Zig 真正的价值不在于那几毫秒的执行速度,而在于它能让你脱离复杂的 MinGW 环境,实现‘一行命令、全平台编译、零依赖部署’的极致开发体验。这是一种用少许性能损耗换取开发效率的典型权衡。

小结

在 Windows 上处理 cgo 编译,Scoop + GCC 是最快的基础方案。但如果追求构建环境的整洁,或者有跨平台编译的需求,Scoop + Zig 是一个在技术设计上更先进的选择。

通过这种方式,我们可以避开重量级的 Visual Studio 或复杂的 MinGW 环境,保持开发环境的纯净和高效。

微信公众号:「程序设计实验室」 专注于互联网热门新技术探索与团队敏捷开发实践,包括架构设计、机器学习与数据分析算法、移动端开发、Linux、Web前后端开发等,欢迎一起探讨技术,分享学习实践经验。