RobotGo 剪贴板操作指南:跨平台 Clipboard 读写原理与 gocopy/gopaste 实战
2026/9/23 17:21:31 网站建设 项目流程

RobotGo 剪贴板操作指南:跨平台 Clipboard 读写原理与 gocopy/gopaste 实战

【免费下载链接】robotgoRobotGo, Go Native cross-platform RPA, GUI automation, Auto test and Computer use @vcaesar项目地址: https://gitcode.com/gh_mirrors/ro/robotgo

导读

RobotGo 仓库中的clipboard子包为 Go 程序提供了跨平台(Windows / macOS / Linux/Unix)的剪贴板文本读写能力,并附带gocopygopaste两个可直接使用的命令行工具,是 GUI 自动化(如复制文本后模拟Ctrl+V粘贴)的重要基础组件。本文基于 clipboard/README.md 展开,结合仓库源码与测试,讲解其平台实现原理、API 用法、命令行操作与常见注意事项,读完即可在自己的 Go 程序或 Shell 脚本中完成剪贴板读写。

clipboard 子包是什么

clipboard目录是一个以 atotto/clipboard:

// ReadAll read string from clipboard func ReadAll() (string, error) { return readAll() } // WriteAll write string to clipboard func WriteAll(text string) error { return writeAll(text) } // Unsupported might be set true during clipboard init, // to help callers decide whether or not to // offer clipboard options. var Unsupported bool

核心接口只有两个函数和一个包级布尔变量:

  • ReadAll() (string, error):从剪贴板读取当前文本内容;
  • WriteAll(text string) error:把字符串写入剪贴板;
  • Unsupported:在包初始化(init())阶段置位,若当前环境没有可用的剪贴板后端(如 Linux 下既无xclip也无xsel),则为true,调用方可以据此判断是否向用户提供剪贴板功能。

上层 API 同时被 RobotGo 根包重新导出,见 robotgo_pub.go:顶层robotgo.ReadAll()robotgo.WriteAll()直接委托给 clipboard 包实现,方便统一调用。

平台支持与底层实现原理

README 声明的支持平台为:

  • OSX(macOS):通过系统自带的pbpaste/pbcopy命令实现;
  • Windows 7(大概率兼容其他 Windows 版本):通过 Win32 API 实现;
  • Linux / Unix:需要系统预装xclipxsel命令行工具。

macOS:pbcopy / pbpaste

实现位于 clipboard/clipboard_darwin.go,通过os/exec调用系统命令:

  • 读取:pbpaste的标准输出即剪贴板文本;
  • 写入:把字符串写入pbcopy的标准输入。

darwin版本没有Unsupported判定逻辑,因为 macOS 上这两个命令由系统自带,几乎总是可用。

Windows:Win32 剪贴板 API

实现位于 clipboard/clipboard_windows.go,通过syscall直接调用user32.dllkernel32.dll

  • OpenClipboard/CloseClipboard打开、关闭剪贴板;
  • EmptyClipboard清空剪贴板;
  • GlobalAlloc(GMEM_MOVEABLE, ...)GlobalLockGlobalUnlocklstrcpyW分配并填充全局内存;
  • SetClipboardData(CF_UNICODETEXT, h)/GetClipboardData(CF_UNICODETEXT)读写Unicode(UTF-16)文本cfUnicodetext = 13)。

值得注意的细节:

  • 写入时分配的内存必须带GMEM_MOVEABLE(0x0002)标志,这与 Win32 文档要求一致;成功后把句柄置 0 以抑制 defer 中的GlobalFree清理,避免重复释放(源码注释"suppress deferred cleanup");
  • waitOpenClipboard()在剪贴板被其他进程占用时会最多等待约 1 秒(循环中每次time.Sleep(time.Millisecond)),超时返回错误,避免直接失败;
  • 读取时用syscall.UTF16ToString把 UTF-16 缓冲转为 Go 字符串。

Linux / Unix:xclip 或 xsel

实现位于 clipboard/clipboard_unix.go,构建标签为freebsd || linux || netbsd || openbsd || solaris || dragonfly。初始化顺序如下:

  1. 默认使用xclip参数:xclip -in -selection clipboard(写入)、xclip -out -selection clipboard(读取);
  2. exec.LookPath(xclip)检测xclip是否在 PATH 中,存在则直接使用;
  3. 否则改用xselxsel --input --clipboard(写入)、xsel --output --clipboard(读取);
  4. 两者都找不到时,把包级变量Unsupported置为true

因此,在 Linux 服务器或精简桌面环境(如无 X 剪贴板工具的容器)中运行前,需要先安装二者之一,例如:

# Debian / Ubuntu sudo apt-get install xclip # 或 sudo apt-get install xsel # RHEL / CentOS / Fedora sudo yum install xclip

此外,Unix 实现还提供了一个包级开关Primary bool,置为true后会去掉命令参数中的--clipboard/-selection clipboard,转而读写 X11 的PRIMARY(主选择区),而不是 CLIPBOARD 剪贴板。该特性也记录在 docs/CHANGELOG.md("Add clipboard choose primary mode on unix")。当Unsupported == true时,ReadAll/WriteAll会直接返回errMissingCommandsNo clipboard utilities available. Please install xsel or xclip

使用限制:仅文本、仅 UTF-8

README 明确列出两条硬性限制:

  • Text string only:只支持纯文本,不支持图片、富文本、文件等剪贴板数据类型;
  • UTF-8 text encoding only (no conversion):只按 UTF-8 处理,不做编码转换

这意味着:如果你的程序输入是 GBK 等其他编码的字符串,需要先自行转为 UTF-8 再调用WriteAll;读取时拿到的也是 UTF-8 字符串(Windows 端内部用 UTF-16 与系统交互,但对外统一转成 UTF-8 字符串返回)。测试代码 clipboard/clipboard_test.go 对这一点做了充分验证:用例覆盖日语"日本語"、法语字符"French: éèêëàùœç"以及 emoji"💩☃",写入后再读出并要求完全一致。注意该测试文件构建标签为darwin || windows,Linux 上不会参与编译,因为测试依赖系统剪贴板环境。

在 Go 程序中使用

安装(README 给出的原始方式):

$ go get github.com/atotto/clipboard

在 RobotGo 仓库内,可以直接导入本地子包:

import "github.com/go-vgo/robotgo/clipboard" func main() { // 写入剪贴板 err := clipboard.WriteAll("Hello, RobotGo") if err != nil { panic(err) } // 读取剪贴板 text, err := clipboard.ReadAll() if err != nil { panic(err) } println(text) }

仓库自带完整可运行示例 clipboard/example/example.go,演示了"写入 → 读取 → 校验非空"的完整流程,并把错误通过log输出而不是直接忽略:

err := clipboard.WriteAll("日本語") if err != nil { log.Println("clipboard write all error: ", err) } text, err := clipboard.ReadAll() if err != nil { log.Println("clipboard read all error: ", err) return } if text != "" { log.Println("text is: ", text) }

在 RobotGo 上层,还可以直接用根包 API(robotgo_pub.go):

  • robotgo.ReadAll():读取剪贴板文本;
  • robotgo.WriteAll(text):写入文本;
  • robotgo.Paste(str)先写入剪贴板,再自动按下cmd + v(在 Windows/Linux 上映射为Ctrl+V,实现"编程式粘贴",这是 GUI 自动化里最常见的组合用法;
  • robotgo.PasteStr(str):已标记 Deprecated,建议改用Paste()

命令行工具:gocopy 与 gopaste

README 提供了两个可直接从 Shell 调用的命令,分别对应"复制"与"粘贴",非常适合在脚本里使用。

gopaste:把剪贴板内容输出到标准输出

$ go get github.com/atotto/clipboard/cmd/gopaste $ # example: $ gopaste > document.txt

实现见 clipboard/cmd/gopaste/gopaste.go:调用clipboard.ReadAll()读回剪贴板文本,再用fmt.Print(text)打印到标准输出。因此gopaste > document.txt等价于"把当前剪贴板内容存成文件",也可直接作为管道上游使用。

gocopy:从标准输入读入并写入剪贴板

$ go get github.com/atotto/clipboard/cmd/gocopy $ # example: $ cat document.txt | gocopy

实现见 clipboard/cmd/gocopy/gocopy.go:先用io.ReadAll(os.Stdin)读尽标准输入,再调用clipboard.WriteAll(string(out))写入剪贴板。因此cat document.txt | gocopy等价于"把文件内容放进剪贴板",配合管道还可以做任意文本处理后再复制,例如:

# 把命令输出复制进剪贴板 df -h | gocopy # 从剪贴板取数并处理 gopaste | grep keyword

两个命令的错误处理都很直接:出错时panic(err),便于脚本在异常时得到非零退出与明确报错。另外在 RobotGo 仓库内,也可以用相对路径方式运行这些命令:

go run clipboard/cmd/gopaste/gopaste.go go run clipboard/cmd/gocopy/gocopy.go

测试与性能基准

clipboard/clipboard_test.go 中除了功能用例,还包含两个基准测试:

  • BenchmarkReadAll:反复读取剪贴板,测量读性能;
  • BenchmarkWriteAll:以日语文本"いろはにほへと"反复写入,测量写性能。

可以用标准方式运行(需要darwinwindows环境):

go test -bench=. ./clipboard

由于读写底层都会 fork 系统命令(macOS 的 pbcopy/pbpaste)或调用 Win32 API,基准数据会受系统剪贴板状态与进程调度影响,更适合作为相对参考而非精确性能指标。从 CHANGELOG 还可以看到,该包在历次迭代中修复过 Windows 剪贴板内存泄漏("Fix windows clipboard memory leak")、完善过错误处理("update clipboard error hand")并加入 primary mode,说明这一定位于基础组件的小包也经历了持续打磨。

注意事项与最佳实践

  1. Linux 环境先装依赖:未安装xclip/xsel时,Unsupported会被置位,读写会返回errMissingCommands。调用方应优先检查该布尔值并给出友好提示。
  2. 编码问题:只支持 UTF-8,其他编码必须先转换;Windows 端内部虽用 UTF-16 交互,但对外 API 仍是 UTF-8 字符串,无自动转换。
  3. 剪贴板占用:Windows 实现内部已做最多约 1 秒的重试等待;其他平台由系统命令负责,一般无需额外处理。
  4. 只处理文本:无法读写图片或文件格式,需要这类能力时应使用 RobotGo 的位图(img.go相关 API)等其他手段。
  5. 配合自动化:在 RPA / GUI 自动化场景中,robotgo.Paste(str)(写剪贴板 + 触发粘贴快捷键)是最常用组合;而robotgo.ReadAll()则常用于"粘贴后回读结果"做断言。

总结

RobotGo 的clipboard子包以极小的 API 面(ReadAll/WriteAll/Unsupported)屏蔽了三大平台的剪贴板差异:macOS 依赖pbcopy/pbpaste,Windows 走 Win32 API,Linux/Unix 则基于xclipxsel命令。配合gocopy/gopaste两个命令行工具,无论是 Go 代码内复制粘贴、Shell 管道处理,还是与robotgo.Paste组合完成自动化输入,都能开箱即用。使用前请务必确认平台依赖(尤其 Linux)与 UTF-8 编码前提,这是避免踩坑的关键。

【免费下载链接】robotgoRobotGo, Go Native cross-platform RPA, GUI automation, Auto test and Computer use @vcaesar项目地址: https://gitcode.com/gh_mirrors/ro/robotgo

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询