RobotGo CHANGELOG 深度解读:从 v0.44 到 v0.100 的核心功能演进与源码实现
RobotGo CHANGELOG 深度解读:从 v0.44 到 v0.100 的核心功能演进与源码实现
本篇文章以 RobotGo 官方 CHANGELOG 为骨架,系统梳理这款 Go 原生跨平台桌面自动化(RPA/GUI Automation)库从 v0.44.0 到 v0.100.0 的版本演进脉络,覆盖图像与位图处理、屏幕捕获、键盘鼠标模拟、全局事件监听、窗口与进程管理、剪贴板、OCR、多屏与缩放适配等核心能力,并结合仓库源码验证关键 API 的真实签名与调用方式。读完本文,你将掌握 RobotGo 各版本功能差异、最新 v0.100.0 图像处理能力的使用方法,以及如何通过源码定位与验证这些能力。
一、版本体系与命名约定
RobotGo 的版本号采用 vX.Y.Z 三段式,并在大版本上使用世界著名山峰命名代号。当前 CHANGELOG 记录的最高版本为 RobotGo v0.100.0, MT. Baker(贝克山),而仓库源码 robotgo_pub.go 中定义的运行版本常量为:
const (
// Version get the robotgo version
Version = "v2.00.0.1658, MT. Baker!"
)
可见当前仓库主线已进入 v2.00 开发周期,同时保留 MT. Baker 代号。版本代号演进一览:
| 版本 | 代号 | 主题重点 |
|---|---|---|
| v0.44.0 | Mount Kailash | 引入 CHANGELOG,整理 Fedora 依赖 |
| v0.45.0 | Mount Qomolangma | 进程管理、剪贴板、TypeStr、FreeBitmap |
| v0.46.x | Pyrenees Mountains | ActivePID、FindBit、去 zlib/libpng 依赖 |
| v0.47.0 | Mount Cook | FindColorCS、kill 进程、平台依赖打包 |
| v0.48.0 | Ben Nevis | 类型转换体系、SaveCapture、颜色处理 |
| v0.49.0 | Olympus Mons | UTF-8 输入、滚轮 x/y、MicroSleep |
| v0.50.0 | The Appalachian Mountains | OCR、findBitmap/findColor 容差优化、缩放 |
| v0.60.0 | Mount Olympus: Mytikas | 窗口句柄与 GetBounds、FindCBitmap |
| v0.70.0 | Caloris Montes | sendInput 重写、numpad 键、KeyTap 错误返回 |
| v0.80.0 | Sierra Nevada | 异步事件、AddEvents/AddMouse |
| v0.90.0 | MT. Rainier | gohook 并发 API、多屏、系统缩放、drag smooth |
| v0.100.0 | MT. Baker | 图像/位图增强、ARM 支持、FindEvery* 系列 |
二、图像与位图处理:v0.100.0 的重头戏
v0.100.0(MT. Baker)的核心主题是 bitmap 与 image 能力增强,同时加入 macOS M1 与 Windows ARM 架构支持。CHANGELOG 中新增的 API 清单包括:
ImgToBitmap():将标准image.Image转换为 RobotGoBitmapToImg():对应源码中实际实现为ToImage(),将C.MMBitmapRef转换为标准image.ImageFindEveryBitmap()/FindEveryColor():查找屏幕上所有匹配的位图/颜色点Save()/Read()/SaveJpeg():图片文件读写与 JPEG 保存ToRGBA():位图转*image.RGBARGBAToBitmap():*image.RGBA转Bitmap- 更多 image 转换函数与 byte→image 转换函数
这些函数在仓库中的实际实现分布在 img.go 与 robotgo.go:
// img.go
// Save create a image file with the image.Image
func Save(img image.Image, path string, quality ...int) error {
return imgo.Save(path, img, quality...)
}
// SaveJpeg save the image by image.Image
func SaveJpeg(img image.Image, path string, quality ...int) error {
return imgo.SaveToJpeg(path, img, quality...)
}
// Read read the file return image.Image
func Read(path string) (image.Image, error) {
return imgo.Read(path)
}
对应实现见 img.go。其中 Save() 与 SaveJpeg() 均支持可变参数 quality(JPEG 质量 0-100),与 README 中 robotgo.SaveJpeg(img1, path1+".jpeg", 50) 的用法一致。
2.1 位图与标准图像的双向转换
v0.100.0 强调 "add more image convert function",核心是打通 C 位图(C.MMBitmapRef)与 Go 标准库 image.Image 之间的双向桥接:
// img.go
// RGBAToBitmap convert the standard image.RGBA to Bitmap
func RGBAToBitmap(r1 *image.RGBA) (bit Bitmap) {
bit.Width = r1.Bounds().Size().X
bit.Height = r1.Bounds().Size().Y
bit.Bytewidth = r1.Stride
src := ToUint8p(r1.Pix)
bit.ImgBuf = src
bit.BitsPixel = 32
bit.BytesPerPixel = 32 / 8
return
}
// ImgToBitmap convert the standard image.Image to Bitmap
func ImgToBitmap(m image.Image) (bit Bitmap) {
bit.Width = m.Bounds().Size().X
bit.Height = m.Bounds().Size().Y
pix, stride, _ := imgo.EncodeImg(m)
bit.Bytewidth = stride
src := ToUint8p(pix)
bit.ImgBuf = src
bit.BitsPixel = 32
bit.BytesPerPixel = 32 / 8
return
}
参见 img.go。注意 ToUint8p() 在拷贝像素时完成了 BGRA → RGBA 通道重排(src<a href="https://link.gitcode.com/i/dfcdf4592063ed1d12b9887afaccba5d" target="_blank">i+3] = dst[i+3]; src[i] = dst[i+2]; ...),这是位图底层像素布局与 Go 标准图像格式的关键适配点,详见 [img.go。
反向转换 ToRGBAGo()(img.go)则把 Bitmap.ImgBuf 按同样规则还原为标准 image.RGBA,Stride 取自 Bytewidth。而 robotgo.go 中的 ToImage() 与 ToRGBA() 直接封装了这一过程:
// robotgo.go
// ToImage convert C.MMBitmapRef to standard image.Image
func ToImage(bit CBitmap) image.Image {
return ToRGBA(bit)
}
见 robotgo.go。CBitmap、Bitmap、C.MMBitmapRef、image.Image 之间的完整转换矩阵可参考 docs/keys.md 的 "Type Conversion" 表格。
2.2 从截屏到位图的完整链路
结合 screen.go 与 robotgo.go 可以看出 v0.100.0 图像能力的完整调用链:
CaptureScreen(x, y, w, h, displayId...)捕获屏幕区域,返回CBitmap(C 结构),见 robotgo.go;CaptureImg()内部调用CaptureScreen后经ToImage转为image.Image并自动FreeBitmap,见 robotgo.go;Capture()(screen.go)则是纯 Go 的截屏路径,返回*image.RGBA,支持通过全局变量DisplayID或第 5 个参数指定显示器;- 截屏结果可通过
Save()/SaveJpeg()/SavePng()落盘,或通过ImgToBitmap()转回位图用于模板匹配。
测试用例 robotgo_test.go 的 TestImage 完整验证了"截屏 → ToImage → SavePng → CaptureImg → Save(jpeg) → ImgToBitmap"这条链路:
func TestImage(t *testing.T) {
bit := CaptureScreen()
defer FreeBitmap(bit)
img := ToImage(bit)
err := SavePng(img, "robot_test.png")
img1, err := CaptureImg(10, 10, 20, 20)
e := Save(img1, "robot_img.jpeg", 50)
tt.Equal(t, 20, Width(img1))
bit1 := ImgToBitmap(img1)
tt.Equal(t, bit1.Width, Width(img1))
}
2.3 FindEveryBitmap 与 FindEveryColor
v0.100.0 新增 FindEveryBitmap() 与 FindEveryColor(),用于返回屏幕上所有匹配位置(区别于传统只返回首个匹配的 FindBitmap/FindColor)。CHANGELOG 同步提到 "add free and find all point function"——即配合 FreeBitmapArr() 批量释放捕获的位图,以及遍历全部匹配点。这类"查找全部"能力在游戏辅助、UI 元素识别与多实例定位场景中非常实用。完整的位图查找 API 生态还包含 vcaesar/bitmap 仓库的 Find / FindAll(README 示例中使用),与 RobotGo 的 CaptureScreen、ToCBitmap 配合使用。
三、屏幕捕获与多显示器支持
3.1 多屏能力的时间线
多显示器支持是 v0.90.0(MT. Rainier)的重点,CHANGELOG 记录:
getMousePos()多屏支持- move smooth 多屏支持
- 全平台系统 scale 支持
- screen 与 bitmap 多屏支持
- 新增
int32_t类型支持 ToBitmapBytes(#204)
源码中多屏的核心入口是 DisplayID 全局变量(默认 -1,见 robotgo_pub.go)与 GetDisplayBounds(i):
// screen.go
func GetDisplayBounds(i int) (x, y, w, h int) {
bs := screenshot.GetDisplayBounds(i)
return bs.Min.X, bs.Min.Y, bs.Dx(), bs.Dy()
}
见 screen.go。多屏遍历截图的标准写法(来自 examples/screen/main.go):
num := robotgo.DisplaysNum()
for i := 0; i < num; i++ {
robotgo.DisplayID = i
img1, _ := robotgo.CaptureImg()
robotgo.Save(img1, "save_"+strconv.Itoa(i)+".png")
robotgo.SaveJpeg(img1, "save_"+strconv.Itoa(i)+".jpeg", 50)
x, y, w, h := robotgo.GetDisplayBounds(i)
img3, err := robotgo.CaptureImg(x, y, w, h)
robotgo.Save(img3, path1+"_1.png")
}
3.2 屏幕缩放(Scale)体系
v0.50.0 引入 "get Scale and GetScaleSize func, get primary display DPI scale factor fix #129, #135",并支持 Custom DPI Scaling 与 scale 默认值。相关源码实现:
SysScale(displayId...):获取系统缩放因子,见 robotgo.go;ScaleF()/Scaled0(x, f)/Scaled1(x, f):缩放换算,见 robotgo_pub.go;GetScaleSize():返回按缩放后的屏幕尺寸,见 robotgo.go;GetScreenSize():返回主屏原始尺寸,见 robotgo.go。
MoveScale()(robotgo.go)在 Scale 开启或 Windows 平台下自动对鼠标坐标做缩放修正,保证高分屏 DPI 缩放下坐标依然准确。
四、键盘与鼠标模拟的演进
4.1 v0.70.0:底层 API 重写
v0.70.0(Caloris Montes)对输入模拟做了关键重构:
- Windows 键盘改用
sendInput而非keybd_event; - Windows 鼠标改用
sendInput而非mouse_event; - 新增 drag mouse 其他按钮支持、更多 numpad 键、
"insert"/"printscreen"的 Mac 支持、millisleep、keyTap错误返回; - 增加
"ctrl"/"cmd"缩写、"capslock"/"numpad_lock"、左右Ctrl/Shift/Alt/command键区分; check key flags支持"cmd"与"ctrl"。
当前源码中 KeyTap / KeyToggle / Type 等函数位于 key.go,键名映射表 keyNames 定义于 key.go,覆盖:
- 功能键
f1-f24; - 修饰键
cmd/cmdl/cmdr/command、alt/altl/altr、ctrl/ctrll/ctrlr/control、shift/shiftl/shiftr/right_shift; - 小键盘
num0-num9、num_lock、num+、num-、num*、num/等; - 多媒体键
audio_mute/vol_down/vol_up/play/stop/prev/next等。
键位完整清单见 docs/keys.md。
4.2 v0.90.0:类型系统与参数灵活性
- keycode 类型改用
uint16与 gohook 对齐,不再做类型转换; keyTap/keyToggle支持"...string"参数(Fixed #209),即KeyTap("i", "alt", "cmd")或KeyTap("i", []string{"alt", "cmd"})两种写法;- 新增
KeyTap() args[2] delay支持(第三个参数为延迟); - 新增
key_Toggles()C 函数、Is64Bit()、SetDelay(); MoveMouseSmooth支持低/高随机速度区间参数(low, high float64, mouseDelay int),底层调用C.smoothlyMoveMouse,见 robotgo.go。
全局延迟变量 MouseSleep / KeySleep 定义于 robotgo_pub.go,SetDelay(d...)(robotgo_pub.go)可一次性设置二者:
// SetDelay sets the key and mouse delay
// robotgo.SetDelay(100) option the robotgo.KeySleep and robotgo.MouseSleep = d
func SetDelay(d ...int) {
v := 10
if len(d) > 0 {
v = d[0]
}
KeySleep = v
MouseSleep = v
}
4.3 鼠标能力清单
鼠标 API 集中在 robotgo.go 的 Mouse 区段(L464-L854):
| 函数 | 能力 | 关键参数 |
|---|---|---|
Move(x, y) |
移动鼠标 | 多屏坐标,自动 Scale 换算 |
MoveSmooth(x, y, low, high, delay) |
拟人化平滑移动 | low/high 随机速度区间 |
DragSmooth(x, y) |
平滑拖拽 | 自动 left down → move → up |
Click(button, double) |
单击/双击,返回 error | 按钮:left/center/right/wheel* |
MultiClick(button, count) |
多次点击 | macOS 走 doubleClick 底层 |
Toggle(button, "up") |
按下/抬起 | MouseDown/MouseUp 封装 |
Scroll(x, y) / ScrollDir(n, dir) / ScrollSmooth(...) |
滚轮 | 支持四方向与平滑滚动 |
MoveRelative / MoveSmoothRelative |
相对移动 | 基于 Location() 计算 |
按钮映射由 CheckMouse()(robotgo.go)与 MouseButtonString()(robotgo.go)维护,支持 left/center/right/wheelDown/wheelUp/wheelLeft/wheelRight。相关测试见 robotgo_test.go。
五、全局事件监听:hook 的演进
事件监听(hook)经历了两次大版本重构:
- v0.80.0(Sierra Nevada):新增异步事件支持、多个 keypress 监听器、
AddEvents/AddMouse/AddMousePoshook 函数、AddEvent "center"支持,修复 #98/#61/#69/#196/#89/#138 等事件相关 issue; - v0.90.0(MT. Rainier):迁移至 gohook 的现代并发 API(
hook.Register+hook.Process),新增 gohook 示例。
v0.80.0 还修复了 go1.12 构建错误(_Ctype_char → C.char,#191)与 hook 的 json break bug(#195)。当前 hook 功能已拆分为独立库 github.com/robotn/gohook 的 Requirements 小节)。
六、窗口与进程管理
窗口与进程 API 在多版本中持续沉淀:
6.1 窗口能力(v0.60.0 集中爆发)
v0.60.0(Mount Olympus: Mytikas)新增:
GetBounds(含get_client/get_frameC 函数);GetXId/GetXidFromPid;GetTitle()重构支持按 pid 查询;CloseWindow()重构支持按 pid;SetHandPid()/GetHandPid();FindCBitmap。
v0.50.0 则补充了 GetForegroundWindow、FindWindow、max/min window API 与 win32.h。v0.49.0 中 activePid 支持 Windows 通过 hwnd 激活;v0.48.0 新增 ActiveName(按窗口名激活)。
6.2 进程能力(v0.45.0 奠基)
v0.45.0(Mount Qomolangma)建立了完整的进程管理 API 并沿用至今:
Pids():获取全部进程 ID;FindName(pid)/FindNames():按 ID 查名称 / 列全部名称;FindIds(name):按名称查 ID;PidExists(pid):判断进程是否存在;Process():进程信息结构;FreeBitmap与文档同步更新。
v0.90.0 将 gops 相关代码迁至 ps.go 统一管理,并补充 FindPath() 与 gops 测试。测试覆盖见 robotgo_test.go 的 TestPs。
七、剪贴板、文本输入与 UTF-8 支持
剪贴板能力从 v0.45.0 的 ReadAll/WriteAll 起步,v0.49.0 增加 Unix 剪贴板 primary 模式选择,v0.90.0 完善错误处理(PasteStr 返回 error),v0.100.0 更新剪贴板代码并新增 paste string err 返回。当前实现位于独立包 clipboard/clipboard.go,通过 robotgo_pub.go 暴露:
// ReadAll read string from clipboard
func ReadAll() (string, error) { return clipboard.ReadAll() }
// WriteAll write string to clipboard
func WriteAll(text string) error { return clipboard.WriteAll(text) }
// Paste paste a string (supported UTF-8),
// write the string to clipboard and tap `cmd + v`
func Paste(str string) error {
err := clipboard.WriteAll(str)
if err != nil {
return err
}
return CmdV()
}
其中 CmdV()(robotgo_pub.go)利用 CmdCtrl() 自动适配平台——macOS 返回 "cmd",其他平台返回 "ctrl",实现"写入剪贴板 + 模拟粘贴快捷键"的可靠文本输入方案。
文本输入方面:v0.48.0 新增 CharCodeAt、UnicodeType、PasteStr 并强化 TypeStr/TypeString;v0.49.0 为 Linux 增加 UTF-8 输入支持;v0.90.0 优化 X11 下的 type string 实现并修复 sleep 时序。v0.100.0 还导出 ToUC()(字符串转 Unicode 表示)并补充测试,相关测试见 robotgo_test.go 的 TestTypeStr:
s1 := "abc\\\\cd/s@世界"
uc := ToUC(s1)
tt.Equal(t, "[a b c \\ \\ c d / s @ U4e16 U754c]", uc)
八、OCR 与简单图像识别
v0.50.0 引入 "simple ocr support"。当前仓库存在两种 GetText 实现:
- 默认实现(img.go):直接调用系统
tesseract命令行,-l指定语言,默认eng,传"zh"时自动映射为chi_sim; - OCR build tag 实现(robotgo_ocr.go):通过
gosseract库,需以-tags ocr编译。
// robotgo_ocr.go (build: ocr)
func GetText(imgPath string, args ...string) (string, error) {
var lang = "eng"
if len(args) > 0 {
lang = args[0]
if lang == "zh" {
lang = "chi_sim"
}
}
client := gosseract.NewClient()
defer client.Close()
client.SetImage(imgPath)
client.SetLanguage(lang)
return client.Text()
}
依赖项 github.com/otiai10/gosseract/v2 已声明于 go.mod。
九、平台支持与构建体系演进
9.1 依赖治理时间线
- v0.46.x:新增无 zlib/libpng 依赖的 robot 分支;
- v0.47.0:正式移除 zlib/libpng 依赖,为 Windows 32/64 位与 macOS 打包依赖,解决安装问题 #72;
- v0.48.0:补充 Windows 32/64 位依赖与 macOS 依赖;
- v0.60.0:统一 pub 数据(
Move public mdata to pub),将部分方法迁至 pub.h; - v0.90.0:gops 迁至 ps.go,移除 vendor 目录,改用 go mod;
- v0.100.0:
go.mod升级至 go 1.25.0(当前仓库 go.mod),新增 macOS M1 与 Windows ARM 支持。
9.2 纯 Go(Cgo-free)后端
CHANGELOG 记录 v0.90.0 "Refactor some C code to Go" 的方向,当前 README 已明确支持通过 build tag 选择纯 Go 后端,无需 GCC/MinGW/Xcode:
| 后端 | Build tag | 说明 |
|---|---|---|
| Windows | win |
纯 Go Win32 |
| macOS | mac |
purego 动态加载 Quartz |
| X11 | x11 |
纯 Go X 协议 |
| Wayland | wayland |
wlroots 合成器(Sway/Hyprland) |
| libei | libei |
GNOME/KDE 的 xdg-desktop-portal |
| 默认 | purego |
按平台自动选择 |
对应包目录为 win/、darwin/、x11/、wayland/、libei/,顶层通过 robotgo.go 的 build tag 条件编译切换实现。
9.3 CI 演进
CHANGELOG 记录了完整的 CI 演进:Appveyor(Windows)→ CircleCI → GitHub Actions(go.yml),Go 版本从 1.10 逐步升级至 1.17+(gofmt build tag 兼容),并补充 codecov 覆盖率与 xvfb 无头测试支持(v0.90.0 "add xvfb run codecov test")。
十、关键修复盘点
CHANGELOG 中值得关注的代表性修复(含 issue 编号):
| 版本 | 修复内容 |
|---|---|
| v0.48.0 | macOS 按 pid 激活、Windows active by pid #101、FindColor 容差 |
| v0.49.0 | Mac 输入法 keytap 失效、move smooth 速度 #96、XFlush 事件刷新 |
| v0.50.0 | findBitmap/findPic 内存泄漏、windows 剪贴板内存泄漏、activePid #140 |
| v0.60.0 | type_string 丢字符 #155、GetWindowText 返回局部变量地址 |
| v0.70.0 | bitmapClick 参数 bug、scale 示例 #153 |
| v0.80.0 | 异步事件 #196/#89、多监听器 #98/#61/#69、go1.12 构建 #191 |
| v0.90.0 | gohook 并发 map 写入 #202、key Kind #203、AddEvents 多次监听 #213、剪贴板错误处理 #212、x11 鼠标 is_drag #3 |
| v0.100.0 | 反斜杠消失 #351、C char* 数组拷贝 #258、Linux TypeStr 双引号、free bitmap #333、mouse 按钮类型反序、keyCodeForCharFallBack 回退 |
其中 v0.90.0 的 Fixed #202 fatal error: concurrent map writes 与 AddEvents() can't listen correctly multiple times(#213)直接推动了 gohook 现代并发 API 的重构。
十一、从 CHANGELOG 到实战:v0.100.0 图像能力速查
综合 CHANGELOG 与源码,v0.100.0 图像处理的最小可用组合如下:
package main
import (
"fmt"
"github.com/go-vgo/robotgo"
)
func main() {
// 1. 截屏得到 C 位图,记得释放
bit := robotgo.CaptureScreen(10, 10, 30, 30)
defer robotgo.FreeBitmap(bit)
// 2. 位图转标准 image.Image 并保存
img := robotgo.ToImage(bit)
robotgo.Save(img, "test_1.png")
robotgo.SaveJpeg(img, "test_1.jpeg", 80)
// 3. 从文件读回图像,再转回位图用于匹配
img2, err := robotgo.Read("test_1.png")
if err != nil {
fmt.Println(err)
return
}
bit2 := robotgo.ImgToBitmap(img2)
_ = robotgo.ToCBitmap(bit2)
// 4. 像素颜色与尺寸
fmt.Println(robotgo.GetPixelColor(10, 10))
w, h := robotgo.Width(img2), robotgo.Height(img2)
fmt.Println(w, h)
}
使用要点:
CaptureScreen返回的CBitmap必须用defer robotgo.FreeBitmap(bit)释放,多个位图可用FreeBitmapArr(bit...)批量释放;Save/SaveJpeg的quality参数可省略(默认质量)或传 0-100 的 JPEG 质量值;Read/DecodeImg/OpenImg/ByteToImg/StrToImg覆盖文件、字节、base64 三种图片来源;GetText依赖 tesseract 可执行文件(默认实现)或-tags ocr编译。
结语
从 v0.44.0 的依赖整理与 CHANGELOG 奠基,到 v0.100.0 的图像位图增强与 ARM 架构支持,RobotGo 的演进脉络清晰可见:以 C 位图为核心、以 Go 标准图像为桥梁、以多屏缩放为适配层、以纯 Go 后端为未来方向。CHANGELOG 中几乎每一项能力都能在 img.go、robotgo.go、screen.go、key.go、ps.go 等源码与 robotgo_test.go 测试中找到对应实现与验证,这也是阅读与使用该库最可靠的路径。配合 README.md 的安装说明与 docs/keys.md 的键位/类型转换表,即可快速上手这套跨平台桌面自动化工具箱。