我有一个程序试图过滤 NamedPipe 文件。由于它没有按预期工作,所以我打印了结果,但对输出感到惊讶。你能解释一下吗?
\n\npackage main\n\nimport (\n "io/ioutil"\n "log"\n "os"\n)\n\nfunc main() {\n files, err := ioutil.ReadDir(".")\n if err != nil {\n log.Fatal(err)\n }\n for _, info := range files {\n log.Printf("file: %s mode: %x\\n", info.Name(), info.Mode()&os.ModeNamedPipe)\n log.Printf("file: %s mode: %v\\n", info.Name(), info.Mode()&os.ModeNamedPipe)\n log.Printf("file: %s mode: %v\\n", info.Name(), info.Mode()&os.ModeNamedPipe != 0)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这输出
\n\n2020/02/06 18:06:46 file: main.go mode: 2d2d2d2d2d2d2d2d2d2d\n2020/02/06 18:06:46 file: main.go mode: ----------\n2020/02/06 18:06:46 file: main.go mode: false\n2020/02/06 18:06:46 file: status.kch mode: 702d2d2d2d2d2d2d2d2d\n2020/02/06 18:06:46 file: status.kch mode: p---------\n2020/02/06 18:06:46 file: status.kch mode: true\nRun Code Online (Sandbox Code Playgroud)\n\n我不明白的是当我以十六进制打印模式时的输出。我希望模式是一个位设置,而 os.ModeNamedPipe 是一个位掩码。所以我假设info.Mode()&os.ModeNamedPipe当文件不是命名管道时会产生整数 0。但我得到了不同的价值。
我终于找到了如何测试文件是否是命名管道,但它是违反直觉的。
\n\n您能解释一下这些不同的输出吗?
\ninfo.Mode()返回类型为 的值os.FileMode,并且os.ModeNamedPipe也是类型为 的值os.FileMode。所以这将是您想要打印/记录的值的类型。
os.FileMode不仅仅是一个整数类型,它是一个独特的类型并且它实现了fmt.Stringer. 并使用动词、包 doc%x中的规则打印它:
如果格式(对于 Println 等隐式为 %v)对于字符串 (%s %q %v %x %X) 有效,则适用以下两个规则:
如果操作数实现了错误接口,则将调用 Error 方法将对象转换为字符串,然后根据动词(如果有)要求对其进行格式化。
如果操作数实现 String() 字符串方法,则将调用该方法将对象转换为字符串,然后根据动词(如果有)的要求对其进行格式化。
所以FileMode.String()会先调用该方法,然后使用 打印字符串值%x,这意味着:
字符串和字节切片(与这些动词等效处理):
Run Code Online (Sandbox Code Playgroud)%x base 16, lower-case, two characters per byte
因此,您看到的 ( 2d2d2d2d2d2d2d2d2d2d) 是结果的字符串表示形式的 (UTF-8) 字节的十六进制表示形式os.FileMode。如果它不是命名管道,则它是“充满破折号”,否则它有一个前导'p'.
uint32如果您想将其视为数字(是的,os.ModeNamedPipe仅设置了一位) ,则可以将其转换为整数 ( ):
fmt.Printf("as-is : %x\n", os.ModeNamedPipe)
fmt.Printf("hexa string : %x\n", os.ModeNamedPipe.String())
fmt.Printf("default string: %v\n", os.ModeNamedPipe.String())
fmt.Printf("decimal : %d\n", os.ModeNamedPipe)
fmt.Printf("hexa : %x\n", uint32(os.ModeNamedPipe))
fmt.Printf("binary : %b\n", os.ModeNamedPipe)
Run Code Online (Sandbox Code Playgroud)
它输出(在Go Playground上尝试):
as-is : 702d2d2d2d2d2d2d2d2d
hexa string : 702d2d2d2d2d2d2d2d2d
default string: p---------
decimal : 33554432
hexa : 2000000
binary : 10000000000000000000000000
Run Code Online (Sandbox Code Playgroud)