| name | robotgo |
| description | RobotGo 是 Go 语言跨平台桌面自动化(RPA)库,提供鼠标控制、键盘输入、屏幕截图、位图查找、剪贴板读写、进程/窗口管理与全局事件监听等能力,支持 macOS、Windows、Linux 三平台 x86-amd64 与 arm64 架构,适用于 GUI 自动化测试、RPA 流程编排与 AI Computer Use 场景。 |
| tags | ["go","golang","rpa","automation","desktop","screen-capture","mouse","keyboard","clipboard","gui","testing"] |
项目地址: https://github.com/go-vgo/robotgo
官方文档: https://github.com/go-vgo/robotgo#documentation
许可证: Apache-2.0 | 最新版本: v1.0.2(2026-03)| 默认分支: master
生态子库:
概述
RobotGo 是 Go 生态中最成熟的桌面自动化库(GitHub 10.7k+ Star),核心能力覆盖 RPA 全链路:
| 能力域 | 主要 API |
|---|
| 鼠标控制 | Move、MoveSmooth、MoveRelative、Click、Toggle、DragSmooth、Scroll、ScrollDir |
| 键盘控制 | Type、KeyTap、KeyToggle、UnicodeType、WriteAll、ReadAll |
| 屏幕读取 | GetScreenSize、GetPixelColor、DisplaysNum、GetDisplayBounds、Scale |
| 截图/图像 | CaptureScreen、CaptureImg、SaveCapture、Save、SaveJpeg、DecodeImg |
| 位图查找 | bitmap.Find、bitmap.FindAll、bitmap.Open、bitmap.Save |
| 进程/窗口 | FindIds、Process、PidExists、ActivePid、GetTitle、GetBounds、Kill |
| 全局事件监听 | hook.Register、hook.Start、hook.Process、hook.End |
| OpenCV 识别 | gcv.FindImgFile、gcv.FindAllImgFile、gcv.Find、gcv.FindX |
v1.0.0+ 重大变更: v1.0.0(2025-12)起对 API 进行了重构。v1.0.2 移除了旧版 FindBitmap / OpenBitmap / SaveBitmap 等位图函数(迁移至 bitmap 子库)。如需旧 API,使用 v0.100.10(最后一个保留旧位图 API 的版本)。
安装
前置条件
- Go 1.21+(推荐 1.24+)
- GCC 工具链(Cgo 模式必需)
平台安装
brew install go
xcode-select --install
winget install Golang.go
winget install MartinStorsjo.LLVM-MinGW.UCRT
sudo apt install gcc libc6-dev
sudo apt install libx11-dev xorg-dev libxtst-dev
sudo apt install xsel xclip
sudo apt install libpng++-dev
sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev \
libxkbcommon-x11-dev libxkbcommon-dev
sudo dnf install gcc libXtst-devel xsel xclip libpng-devel \
libxkbcommon-devel libxkbcommon-x11-devel xkbcomp-devel
导入与构建
go get github.com/go-vgo/robotgo
Cgo-free 纯 Go 后端(实验性):
CGO_ENABLED=0 go build -tags win
CGO_ENABLED=0 go build -tags wayland
CGO_ENABLED=0 go build -tags libei
核心 API
鼠标控制
package main
import "github.com/go-vgo/robotgo"
func main() {
robotgo.Move(100, 200)
robotgo.MoveSmooth(300, 400)
robotgo.MoveSmooth(300, 400, 5.0, 10.0)
robotgo.MoveRelative(10, -5)
x, y := robotgo.Location()
robotgo.Click()
robotgo.Click("right")
robotgo.Click("center", true)
robotgo.Click("wheelLeft")
robotgo.Toggle("left", "down")
robotgo.Toggle("left", "up")
robotgo.DragSmooth(500, 600)
robotgo.ScrollDir(3, "down")
robotgo.Scroll(0, -5)
robotgo.ScrollSmooth(10)
robotgo.ScrollRelative(0, 5)
}
键盘控制
robotgo.Type("Hello 世界")
robotgo.Type("Hello", pid)
robotgo.UnicodeType(0x4e16)
robotgo.KeyTap("a")
robotgo.KeyTap("ctrl", "c")
robotgo.KeyTap("ctrl", "shift", "t")
robotgo.KeyToggle("shift", "down")
robotgo.KeyToggle("shift", "up")
屏幕读取
w, h := robotgo.GetScreenSize()
color := robotgo.GetPixelColor(10, 10)
num := robotgo.DisplaysNum()
x, y, dw, dh := robotgo.GetDisplayBounds(1)
robotgo.DisplayID = 1
scale := robotgo.Scale()
scaleF := robotgo.ScaleF()
截图与图像
robotgo.SaveCapture("screenshot.png")
robotgo.SaveCapture("region.png", 0, 0, 800, 600)
bit := robotgo.CaptureScreen(0, 0, 800, 600)
defer robotgo.FreeBitmap(bit)
img, err := robotgo.CaptureImg(0, 0, 800, 600)
robotgo.Save(img, "output.bmp")
robotgo.SaveJpeg(img, "output.jpg", 75)
img2, ext, err := robotgo.DecodeImg("photo.png")
goImg := robotgo.ToImage(bit)
位图查找(via bitmap 子库)
import "github.com/vcaesar/bitmap"
bit := bitmap.Open("template.png")
x, y := bitmap.Find(bit)
if x != -1 && y != -1 {
robotgo.Move(x, y)
robotgo.Click()
}
results := bitmap.FindAll(bit)
for _, r := range results {
fmt.Printf("Found at (%d, %d)\n", r.X, r.Y)
}
剪贴板
robotgo.WriteAll("Hello")
text, err := robotgo.ReadAll()
进程与窗口管理
pids, _ := robotgo.FindIds("chrome")
procs, _ := robotgo.Process()
exists, _ := robotgo.PidExists(1234)
name, _ := robotgo.FindName(1234)
robotgo.ActivePid(pids[0])
robotgo.ActiveName("Chrome")
title := robotgo.GetTitle(pids[0])
x, y, w, h := robotgo.GetBounds(pids[0])
robotgo.Kill(pids[0])
ok := robotgo.Alert("提示", "确定要执行吗?")
全局事件监听(via gohook 子库)
package main
import (
"fmt"
hook "github.com/robotn/gohook"
)
func main() {
hook.Register(hook.KeyDown, []string{"q", "ctrl"}, func(e hook.Event) {
fmt.Println("Ctrl+Q pressed, exiting...")
hook.End()
})
hook.Register(hook.MouseDown, []string{}, func(e hook.Event) {
fmt.Printf("Mouse at (%d, %d)\n", e.X, e.Y)
})
s := hook.Start()
hook.Process(s)
}
ok := hook.AddEvent("ctrl")
ok = hook.AddEvents("ctrl", "shift")
OpenCV 图像识别(via gcv 子库)
import "github.com/vcaesar/gcv"
result := gcv.FindImgFile("template.png", "screenshot.png")
fmt.Printf("Found at (%d, %d)\n", result.TopLeft.X, result.TopLeft.Y)
results := gcv.FindAllImgFile("template.png", "screenshot.png")
result := gcv.FindImg(templateImg, sourceImg)
x, y := gcv.FindX(templateImg, sourceImg)
gcv 依赖: 需要安装 OpenCV + GoCV。安装方法参考 GoCV 官方文档。
典型工作流
工作流 1:等待图像出现并点击
func waitAndClick(template string, timeout time.Duration) error {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
img, _ := robotgo.CaptureImg()
result := gcv.FindImgFile(template, "temp.png")
robotgo.Save(img, "temp.png")
if result.TopLeft.X >= 0 {
robotgo.MoveSmooth(result.TopLeft.X+5, result.TopLeft.Y+5)
time.Sleep(100 * time.Millisecond)
robotgo.Click()
return nil
}
time.Sleep(500 * time.Millisecond)
}
return fmt.Errorf("timeout waiting for %s", template)
}
工作流 2:RPA 自动填表
func fillForm() {
pids, _ := robotgo.FindIds("notepad")
if len(pids) > 0 {
robotgo.ActivePid(pids[0])
}
time.Sleep(500 * time.Millisecond)
robotgo.WriteAll("自动填入的内容")
robotgo.KeyTap("ctrl", "v")
robotgo.KeyTap("tab")
robotgo.WriteAll("第二字段")
robotgo.KeyTap("ctrl", "v")
robotgo.KeyTap("enter")
}
工作流 3:全局热键启动器
func hotkeyLauncher() {
hook.Register(hook.KeyDown, []string{"ctrl", "shift", "s"}, func(e hook.Event) {
robotgo.SaveCapture(fmt.Sprintf("shot_%d.png", time.Now().Unix()))
})
hook.Register(hook.KeyDown, []string{"ctrl", "shift", "q"}, func(e hook.Event) {
hook.End()
})
s := hook.Start()
hook.Process(s)
}
延时控制
robotgo.Sleep(2)
robotgo.MilliSleep(500)
robotgo.MouseSleep = 100
robotgo.KeySleep = 50
AI 使用建议
- 优先用 CaptureImg 而非 CaptureScreen:CaptureImg 返回
image.Image 无需手动释放,避免内存泄漏。
- 中文输入用剪贴板:
Type() 可能被活动输入法拦截/转换。中文文本建议 WriteAll() + KeyTap("ctrl", "v")。
- macOS 权限:程序运行前必须授予终端/IDE 的「辅助功能」和「屏幕录制」权限,否则鼠标键盘静默失效、截图全黑。
- 位图模板需同环境截取:
bitmap.Find 要求精确像素匹配,不同分辨率/DPI/主题/抗锯齿下会失败。
- 防无限循环:robotgo 模拟的键鼠事件会被 gohook 捕获。用状态标志区分「程序触发」和「用户操作」。
- v1.0+ API 变更:若从 v0.100.x 迁移,注意
FindBitmap/OpenBitmap/SaveBitmap 已移至 bitmap 子库,GetBitmapSize 改为 GetImgSize(path)。
- CGO 交叉编译极困难:Cgo 模式需要目标平台的 C 交叉工具链和系统头文件。推荐在各平台原生构建,或使用 Cgo-free 后端。
常见问题(FAQ)
| 问题 | 原因 | 解决方案 |
|---|
| macOS 鼠标/键盘无反应 | 未授予权限 | 系统设置 → 隐私与安全性 → 辅助功能 + 屏幕录制 |
| 截图全黑 | 未授予屏幕录制权限 | 同上 |
png.h not found | 缺少 libpng 开发头文件 | Linux: apt install libpng++-dev;Windows: 换用 Cgo-free -tags win |
| Linux 剪贴板报错 | 未安装 xsel/xclip | apt install xsel xclip |
| Wayland 下无法工作 | Wayland 不支持 X11 协议 | 使用 -tags wayland(wlroots)或 -tags libei(GNOME/KDE) |
bitmap.Find 总返回 -1,-1 | 模板与截图环境不一致 | 确保相同分辨率/DPI/缩放/主题下截取模板 |
| Go 1.10.x 编译报错 | Go #24355 缓存 Bug | 升级 Go 到 1.21+ |
| libei 后端截图失败 | libei 仅处理输入 | libei 后端不支持截图/窗口管理,使用 Cgo 模式 |
RobotGo-Pro(商业版)
RobotGo-Pro 是非开源商业版本,提供 JavaScript、Python、Lua 等多语言绑定,包含技术支持和新特性。本技能仅覆盖开源 Go 版本。
参考资源