在Go的os包中使用OpenFile
函数时,管道符的用途究竟是什么?
示例:
os.OpenFile("foo.txt", os.O_RDWR|os.O_APPEND, 0660)
它是否充当逻辑OR
?如果是这样,Go会选择第一个" truthy" ??作为那些标志所代表的常量,它们的核心只是用十六进制编写的整数,在编译时如何选择Go应用哪个标志?
毕竟,如果函数调用的次数最多,os.O_APPEND
将优先于传入的所有其他标志,如下所示:
os.O_RDWR == syscall.O_RDWR == 0x2 == 2
os.O_APPEND == syscall.O_APPEND == 0x400 == 1024
os.O_CREATE == syscall.O_CREAT == 0x40 == 64
要跟进下面的评论,如果我使用os.O_APPEND|os.O_CREATE
进行按位运算符计算,那么如果文件存在则会出现错误,或者只是根据需要创建/追加?
我的问题是双重的,一个是理解按位运算符的目的,我现在理解它更多地用作位掩码运算;二,如何使用os.OpenFile()
函数作为创建或追加操作。在我的游戏中,我发现以下组合效果最好:
file, _ := os.OpenFile("foo.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0660)
file.WriteString("Hello World\n")
file.Sync()
这是正确的方法还是有更简洁的方法来做到这一点?
答案 0 :(得分:4)
这是一个按位,而不是逻辑OR。
如果以二进制形式写出数字,并为每个数字指定真值0/1,并将逻辑OR应用于参数之间的每个位i
,然后将结果重新组合为二进制扩展的整数 - |
运算符的。
它通常以通常被描述为" bitmask"的方式使用。 - 当您希望单个int值表示可以打开或关闭的(小)开关集时,可以使用位掩码。每个开关一位。
在这种情况下,您应该看到A | B
表示A中所有开关都已打开,以及B中所有开关都在"上。在您的情况下,开关定义文件打开/创建功能的确切行为,如the Go manual所述。 (可能更详细的是我上面链接的Unix手册页。)
在位掩码中,通常定义代表每个开关的常量 - 这是如何确定那些O_ *常量的。每个都是一个int,只有一位设置并代表一个特定的开关。 (但是,要小心,因为有时它们代表开关的组合!)。
另外:
^A // All of the "switches" not currently on in A
A&^B // All of the "switches" on in A but not on in B
A^B // All of the "switches" on in exactly one of A or B
等。
Go手册here中描述了运算符|
本身。
答案 1 :(得分:0)
它是一个按位OR运算符。这里使用的目的是允许将多个值作为位掩码传递。因此,您可以组合标志来创建所需的结果,例如,如果文件不存在,则使用OpenFile()
函数创建文件,如果文件不存在则附加到文件。
os.Openfile("foo.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0660
从os包中作为参数传递的常量是从syscall包中赋值的。此程序包包含低级操作系统独立值。
包syscall包含低级操作系统原语的接口。细节因底层系统而异,默认情况下,godoc将显示当前系统的系统调用文档。如果您希望godoc显示另一个系统的系统调用文档,请将$ GOOS和$ GOARCH设置为所需的系统。例如,如果要在linux / amd64上查看freebsd / arm的文档,请将$ GOOS设置为freebsd,将$ GOARCH设置为arm。 syscall的主要用途是在其他软件包中提供一个更便携的系统接口,例如" os"," time"和" net"。
https://golang.org/pkg/syscall/
正如@BadZen所说,一个按位OR运算符,在这种情况下,' |'字符,在二进制级别操作,将任何0值更改为1还不是1。
你应该在这个背景下看到A | B表示" A中所有开关,以及B中所有开关上的所有开关"。
通过上面显示的函数执行此操作,您正在操作函数的行为以创建具有给定名称os.O_CREATE
的文件(foo.txt
)或打开文件以进行读/写( os.O_RDWR
)并且会附加写入的任何值(os.O_APPEND
)。或者,您可以传递os.O_TRUNC
以便在写入之前截断文件。
按位OR运算符允许您组合不同行为的强大解决方案,以便从您希望的函数中获取结果。