Golang中sys包与I/O操作相关的问题求助
Golang中sys包与I/O操作相关的问题求助 由于我想访问一些底层API来使用CreateFile函数执行I/O操作 syscall.CreateFile( name *uint16…) 在此过程中,我遇到了一个问题:name参数的类型是*uint16,但它应该是一个数组([]uint16),以便能够处理UTF-16格式的字符串。正如我们在微软提供的示例中看到的 -> 链接,其中TEXT宏将字符串转换为wchar_t数组,或者我们可以说[]uint16。
提前感谢,如果我说的有误请见谅,因为我在这个领域只是个初学者。
更多关于Golang中sys包与I/O操作相关的问题求助的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感谢,我只是Go语言的初学者,不了解这种情况 😅。感谢指出我的错误。
啊,原来是这样!我以前知道这个,但忘记了! 
要使用这些底层API,我认为你必须使用
unsafe包,并编写类似于这段C代码的Go代码
为什么不使用官方的Go解决方案呢?
import "golang.org/x/sys/windows"
我正在撰写一篇关于如何在GoLang中编写多线程复制程序的博客,这就是我这样做的原因。我想比较实现复制操作的各种方法的性能。例如使用io.copy、os.readfile,以及最后使用依赖于操作系统的底层API。
我能够运行程序,主要问题在于我无法传递正确的文件名,因为该函数只接受单个UTF-16字符,而我想发送一个数组。
像这样的底层不安全 API 可能很难正确使用。我很好奇,为什么你自称是该领域的新手,却首先尝试使用它们呢? 🙂
要使用这些底层 API,我认为你必须使用 unsafe 包,并编写类似于以下 C 代码的 Go 代码:https://gist.github.com/xebecnan/6d070c93fb69f40c3673
skillian: 当你有一个
[]utf16文件名时,你需要像&fileName[0]这样传递它。
官方的 Go 解决方案:
import "golang.org/x/sys/windows"
func UTF16PtrFromString(s string) (*uint16, error)
UTF16PtrFromString 返回指向 UTF-8 字符串 s 的 UTF-16 编码的指针,并添加了终止 NUL 字符。如果 s 在任何位置包含 NUL 字节,则返回 (nil, syscall.EINVAL)。
在Go中使用syscall.CreateFile处理UTF-16字符串时,确实需要将字符串转换为*uint16类型。虽然参数类型显示为*uint16,但实际上它指向的是UTF-16编码的字符数组(相当于C语言中的wchar_t*)。
以下是正确的转换方法:
package main
import (
"golang.org/x/sys/windows"
"syscall"
"unsafe"
)
func main() {
// 要打开的文件名(支持Unicode)
fileName := "C:\\test\\文件.txt"
// 将Go字符串转换为UTF-16指针
utf16FileName, err := syscall.UTF16PtrFromString(fileName)
if err != nil {
panic(err)
}
// 调用CreateFile
handle, err := windows.CreateFile(
utf16FileName, // 文件名(UTF-16)
windows.GENERIC_READ, // 访问模式
windows.FILE_SHARE_READ, // 共享模式
nil, // 安全属性
windows.OPEN_EXISTING, // 创建方式
windows.FILE_ATTRIBUTE_NORMAL, // 文件属性
0, // 模板文件句柄
)
if err != nil {
panic(err)
}
defer windows.CloseHandle(handle)
// 使用文件句柄进行后续操作...
}
或者,如果你需要手动转换字符串,可以使用以下方法:
func stringToUTF16Ptr(s string) *uint16 {
// 将字符串转换为UTF-16切片
utf16 := syscall.StringToUTF16(s)
// 返回切片第一个元素的指针
return &utf16[0]
}
// 使用示例
fileNamePtr := stringToUTF16Ptr("C:\\test\\example.txt")
handle, err := windows.CreateFile(
fileNamePtr,
windows.GENERIC_READ | windows.GENERIC_WRITE,
0,
nil,
windows.CREATE_ALWAYS,
windows.FILE_ATTRIBUTE_NORMAL,
0,
)
关键点:
syscall.UTF16PtrFromString()会自动处理字符串到UTF-16指针的转换- 返回的指针指向一个以null结尾的UTF-16字符串数组
- Windows API期望的是以null结尾的宽字符串,这正是
UTF16PtrFromString提供的格式
对于需要传递字符串数组(多个字符串)的情况,可以使用:
import "golang.org/x/sys/windows"
// 多个文件名的示例
fileNames := []string{"file1.txt", "file2.txt"}
var namePtrs []*uint16
for _, name := range fileNames {
ptr, err := syscall.UTF16PtrFromString(name)
if err != nil {
panic(err)
}
namePtrs = append(namePtrs, ptr)
}
// 现在namePtrs就是[]*uint16,可以传递给需要多个文件名的API
这样就能正确处理UTF-16编码的文件名,并兼容Windows的Unicode API。


