在golang syscall.GetLastError()
中不会返回上一个错误。请参阅以下示例
if handle := _OpenSCManager(machineNamePtr, databaseNamePtr, desiredAccess); handle == nil {
if err := syscall.GetLastError(); err != nil {
return InvalidServiceDatabaseHandleHandle, ServiceErrno(err.(syscall.Errno))
}
}
err
始终为nil
。假设machineNamePtr
是一台不存在的机器。使用c ++和GetLastError()
测试相同的代码抛出RPC server is not available
。那么为什么不在go
?
修改
_OpenSCManager是使用go generate
生成的。
//sys _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle) = advapi32.OpenSCManagerW
func _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle) {
r0, _, _ := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(desiredAcces))
handle = ServiceDatabaseHandle(r0)
return
}
答案 0 :(得分:0)
所以我终于有了这个工作。首先,我尝试使用以下签名//sys _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle, lasterror error) = advapi32.OpenSCManagerW
返回错误变量。但go generate
总是Only last windows error is allowed as second return value...
。但如果将其更改为//sys ... (handle ServiceDatabaseHandle, err error) = advapi32.OpenSCManagerW
,则会成功生成代码。所以你明确要写err error
。有人知道为什么吗?所以现在函数看起来像
func _OpenSCManager(machineName *uint16, databaseName *uint16, desiredAcces ServiceAccessRight) (handle ServiceDatabaseHandle, err error) {
r0, _, e1 := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(desiredAcces))
handle = ServiceDatabaseHandle(r0)
if handle == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
并返回错误。因此无需致电GetLastError()
。
答案 1 :(得分:0)
IIUC,Windows上的syscall.Syscall()
在实际系统调用完成后自动和原子调用GetLastError()
。这应该是可以理解的,一旦你考虑到goroutine从系统调用退出,Go运行时调度程序可以自由地抢占它并在正好运行的刚刚被抢占的goroutine的线程上运行另一个goroutine。 / em>的
由于GetLastError()
访问每线程状态,如果第二个goroutine进行另一个系统调用,它可能会破坏最后一个错误值,因此在Go的上下文中,每个系统调用都应伴随以下对{的调用{1}}在单个系统调用调用的上下文中完成 - 从Go端看。