Go语言如何获取Windows平台已连接摇杆的可用ID列表
Windows平台无依赖枚举摇杆设备ID方案
你使用的摇杆读取库底层本身就是调用Windows原生WinMM(Windows多媒体)系统接口实现的,不需要引入任何需要用户额外安装的第三方依赖,直接通过标准库调用系统自带接口即可完成设备枚举,拿到可直接传入joystick.Open()的有效joy_id。
WinMM是Windows从XP到Win11全版本默认预装的系统组件,编译后的程序是单二进制文件,不需要用户额外安装SDL、运行库等任何附加软件,完全适配非技术用户的使用场景。
核心逻辑
WinMM的摇杆设备ID从0开始连续编号:
- 首先调用
joyGetNumDevs接口获取系统支持的最大摇杆设备数量上限 - 从ID=0开始逐个校验,调用
joyGetDevCaps接口判断对应ID的设备是否真实接入、可用 - 所有校验通过的ID就是可直接使用的有效
joy_id
可直接复用的实现代码
通过Go标准库syscall直接调用系统winmm.dll导出的接口即可,不需要引入额外第三方包:
package main import ( "syscall" "unsafe" ) var ( winmm = syscall.NewLazyDLL("winmm.dll") procJoyGetNumDevs = winmm.NewProc("joyGetNumDevs") procJoyGetDevCapsW = winmm.NewProc("joyGetDevCapsW") ) // JOYCAPS 对应WinMM接口的设备信息结构体,仅保留校验必要字段 type JOYCAPS struct { ManufacturerID uint16 ProductID uint16 DriverName [32]uint16 ProductName [32]uint16 _ [224]byte // 占位剩余不需要读取的结构体字段 } const joyErrNoError = 0 // GetAvailableJoystickIDs 返回所有当前接入可用的摇杆ID,可直接传入joystick.Open使用 func GetAvailableJoystickIDs() []uint32 { var validIDs []uint32 maxDevNum, _, _ := procJoyGetNumDevs.Call() for id := uint32(0); id < uint32(maxDevNum); id++ { var caps JOYCAPS ret, _, _ := procJoyGetDevCapsW.Call( uintptr(id), uintptr(unsafe.Pointer(&caps)), uintptr(unsafe.Sizeof(caps)), ) if ret == joyErrNoError { validIDs = append(validIDs, id) } } return validIDs }
使用注意事项
- 枚举得到的ID和摇杆库要求的参数完全匹配,不需要做额外转换,遍历传入
joystick.Open()即可正常打开设备。 - 设备ID会随手柄插拔动态变化,如果程序需要支持热插拔,定时重新调用该枚举函数刷新设备列表即可。
- 枚举结果和Windows系统自带的「游戏控制器」控制面板里显示的设备完全一致,包括正规手柄、虚拟手柄等所有被系统识别的摇杆类设备。
- 跨平台适配时,Linux下可通过枚举
/dev/input/js*设备节点获取对应设备ID,macOS下可通过IOKit框架接口枚举,Windows下使用上述方案即可。
内容的提问来源于stack exchange,提问作者AndyS
相关产品推荐
相关产品推荐

