我正在编写一个与 Windows Services 交互的 golang 应用程序使用windows/svc包。
当我查看包源代码时,系统调用是如何完成的,我看到了有趣的强制转换构造:
name := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(s.ServiceName))[:]
摘自mgr.go
这是处理 Win32 API 时的一种常见模式,当需要传递预分配的缓冲区以从 Win32 API 函数接收值(通常是数组或结构体)时。
据我所知,Win API 返回一个由其指针表示的 unicode 字符串,并将其传递给 syscall.UTF16ToString(s []uint16)
在本例中,函数将其转换为 go 字符串。
当不安全的指针被转换为指向 1M 数组的指针时,我对这部分感到困惑,*[1<<20]uint16
。
为什么大小是 1M [1<<20]?
值的缓冲区是动态分配的,而不是固定大小 1M。
最佳答案
您需要为数组类型选择静态大小,因此 1<<20
选择足够大以允许调用返回任何合理的缓冲区。
这个尺寸没有什么特别的,有时你会看到 1<<31-1
因为它是 32 位平台最大的数组,或者 1<<30
因为它看起来更好。只要类型可以包含返回的数据,这并不重要。
关于pointers - 为什么 Win32 API 系统调用中使用的缓冲区会转换为 [1<<20]<type> 数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50358533/