为什么golang.org/x/sys包鼓励使用syscall包it';它是用来取代的吗?

为什么golang.org/x/sys包鼓励使用syscall包it';它是用来取代的吗?,go,Go,我读过一些使用syscall与底层操作系统(如Linux或Windows)进行低级交互的Go代码 我想在本机Windows开发中使用相同的软件包,但阅读其文档时说它不推荐使用golang/x/sys: $ go doc syscall package syscall // import "syscall" Package syscall contains an interface to the low-level operating system primitives. ... Depre

我读过一些使用
syscall
与底层操作系统(如Linux或Windows)进行低级交互的Go代码

我想在本机Windows开发中使用相同的软件包,但阅读其文档时说它不推荐使用
golang/x/sys

$ go doc syscall
package syscall // import "syscall"

Package syscall contains an interface to the low-level operating system
primitives.

...

Deprecated: this package is locked down. Callers should use the
corresponding package in the golang.org/x/sys repository instead. That is
also where updates required by new systems or versions should be applied.
See https://golang.org/s/go1.4-syscall for more information.
现在,阅读
golang/x/sys
的文档并检查其代码,它严重依赖并鼓励使用
syscall
包:


为什么
golang/x/sys
依赖并鼓励使用它要替换的软件包?

免责声明:我是一个非常新的专门开发人员(虽然不是针对低级操作系统编程)。不过,这里的道路似乎很清晰

Go,作为一个生态系统,不仅是语言本身,而且所有的各种库都是可移植的。但是直接的系统调用基本上是不可移植的。所以这里会自动产生一些张力

为了做任何有用的事情,Go运行时需要来自操作系统的各种服务,例如创建操作系统级线程、发送和接收信号、打开文件和网络连接等等。这些操作中的许多可以而且已经从操作系统A、B和C上的操作方式抽象为大多数或所有操作系统支持的通用概念。这些抽象基于各种操作系统中的实际机制

他们甚至可以在内部分层执行此操作。例如,查看一下,会显示
文件.go
文件\u平面9.go
文件\u posix.go
文件\u unix.go
,以及
文件\u windows.go
源文件。顶部显示一个
+build
指令:

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
显然,这段代码本身并不是完全可移植的,但它为
os
实现的例程(由
os.File
抽象包装)足以满足所有符合POSIX的系统。例如,这减少了必须放入Unix/Linux特定
文件\u Unix.go
文件中的代码量

在某种程度上,操作系统级的操作可以被包装成更抽象、更可移植的操作,那么,各种内置的Go包就可以做到这一点。例如,您不需要知道是否有不同的系统调用用于打开设备文件、文本文件和二进制文件,或者长路径名和短路径名:您只需调用
os.Create
os.Open
,它就可以在后台执行任何必要的工作

整个想法与系统调用不符。用于创建新UID命名空间的Linux系统调用没有Windows等效项。2 Windows
WaitForMultipleObjects
system调用在Linux上没有真正的等效项。stat/lstat调用的低级细节因系统而异,以此类推

在Go的早期版本中,有人试图用
syscall
包来掩盖这一点。但你引用的链接——将这一尝试描述为,如果没有失败,至少是过度拉伸。“问题”部分的最后一个词是“问题”

这个链接上的建议是,从Go 1.4开始,
syscall
包将被冻结(或大部分冻结):不要在其中添加新功能。但是其中的特性足以实现新的、实验性的
golang.org/x/sys/*
包,或者至少是其中的一些包。实验包借用现有的、正式弃用的
syscall
package(如果这符合实验性新包的需要),没有什么坏处

golang.org/x/
中的内容是实验性的:可以随意使用它们,但要注意,与标准软件包中的内容不同,版本更新中没有兼容性承诺。那么,回答你问题的最后一行:

为什么
golang/x/sys
依赖并鼓励使用它要替换的软件包

它依赖于
syscall
,因为这很好。但它根本不“鼓励使用”
syscall
。它只是在足够的时候使用它。无论出于何种原因,如果这一点变得不够,它将停止依赖它

回答一个您没有问过的问题(但我问过):假设您需要有关文件的Unix特定
stat
信息,例如其inode编号。你可以选择:

info, err := os.Stat(path) // or os.Lstat(path), etc
if err != nil { ... handle error ... }
raw, ok := info.Sys().(*syscall.Stat_t)
if !ok { ... do whatever is appropriate ... }
inodeNumber := raw.Ino
或:

第一段代码的优点是,您可以获得有关文件的所有其他(可移植)信息,例如,文件的模式、大小和时间戳。你也许知道,也许不知道inode的编号;
!好的
case告诉您是否这样做了。这里的主要缺点是需要更多的代码来完成

第二段代码的优点是,它正好表达了您的意思。您可以从
stat
调用中获取所有信息,也可以不获取任何信息。缺点显而易见:

  • 它只在Unix ish系统上工作,并且
  • 它使用一个实验包,其行为可能会改变
所以,这其中哪一项对你来说更重要取决于你


1这是一个隐喻,还是我把它拟人化了。有一条古老的规则:不要把电脑拟人化,他们讨厌这样

2A Linux UID命名空间从容器内的UID映射到容器外的UID。也就是说,在容器中,文件可能由UID1234拥有。如果文件所在的文件系统也安装在容器外部,则该文件可以由其他所有者拥有,可能是5678。更改容器任一“侧”的所有权会更改该侧的名称空间;更改在另一侧显示为通过名称空间映射的ID映射或反向映射的结果

(例如,同样的技巧也适用于NFS UID映射
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
info, err := os.Stat(path) // or os.Lstat(path), etc
if err != nil { ... handle error ... }
raw, ok := info.Sys().(*syscall.Stat_t)
if !ok { ... do whatever is appropriate ... }
inodeNumber := raw.Ino
var info unix.Stat
err := unix.Stat(path, &info) // or unix.Lstat, etc
if err != nil { ... handle error ... }
inodeNumber := unix.Ino