RobotGo CHANGELOG 深度解读:从 v0.44 到 v0.100 的核心功能演进与源码实现

原创2026-09-23 20:07:40930 阅读
文章标签:桌面应用GUI 自动化RPA

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 转换为 RobotGo Bitmap
  • ToImg():对应源码中实际实现为 ToImage(),将 C.MMBitmapRef 转换为标准 image.Image
  • FindEveryBitmap() / FindEveryColor():查找屏幕上所有匹配的位图/颜色点
  • Save() / Read() / SaveJpeg():图片文件读写与 JPEG 保存
  • ToRGBA():位图转 *image.RGBA
  • RGBAToBitmap():*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 图像能力的完整调用链:

  1. CaptureScreen(x, y, w, h, displayId...) 捕获屏幕区域,返回 CBitmap(C 结构),见 robotgo.go;
  2. CaptureImg() 内部调用 CaptureScreen 后经 ToImage 转为 image.Image 并自动 FreeBitmap,见 robotgo.go;
  3. Capture()(screen.go)则是纯 Go 的截屏路径,返回 *image.RGBA,支持通过全局变量 DisplayID 或第 5 个参数指定显示器;
  4. 截屏结果可通过 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/AddMousePos hook 函数、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_frame C 函数);
  • 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 实现:

  1. 默认实现(img.go):直接调用系统 tesseract 命令行,-l 指定语言,默认 eng,传 "zh" 时自动映射为 chi_sim;
  2. 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 的键位/类型转换表,即可快速上手这套跨平台桌面自动化工具箱。

登录后查看全文
robotgo