Как объяснить отображаемое значение для os.FileMode? - PullRequest
1 голос
/ 06 февраля 2020

У меня есть программа, пытающаяся отфильтровать файлы NamedPipe. Поскольку это не сработало, как ожидалось, я распечатал результат, но был удивлен результатом. Вы можете это объяснить?

package main

import (
    "io/ioutil"
    "log"
    "os"
)

func main() {
    files, err := ioutil.ReadDir(".")
    if err != nil {
        log.Fatal(err)
    }
    for _, info := range files {
        log.Printf("file: %s mode: %x\n", info.Name(), info.Mode()&os.ModeNamedPipe)
        log.Printf("file: %s mode: %v\n", info.Name(), info.Mode()&os.ModeNamedPipe)
        log.Printf("file: %s mode: %v\n", info.Name(), info.Mode()&os.ModeNamedPipe != 0)
    }
}

Это выводит

2020/02/06 18:06:46 file: main.go mode: 2d2d2d2d2d2d2d2d2d2d
2020/02/06 18:06:46 file: main.go mode: ----------
2020/02/06 18:06:46 file: main.go mode: false
2020/02/06 18:06:46 file: status.kch mode: 702d2d2d2d2d2d2d2d2d
2020/02/06 18:06:46 file: status.kch mode: p---------
2020/02/06 18:06:46 file: status.kch mode: true

Чего я не понимаю, так это вывод, когда я печатаю Режим в шестнадцатеричном формате. Я ожидал, что режим будет немного установлен, а os.ModeNamedPipe будет битовой маской. Поэтому я предположил, что info.Mode()&os.ModeNamedPipe даст целое число 0, если файл не является именованным каналом. Но я получаю другое значение.

Я наконец-то узнал, как проверить, является ли файл именованным каналом, но он нелогичен.

Не могли бы вы объяснить эти разные выводы?

Ответы [ 2 ]

4 голосов
/ 06 февраля 2020

info.Mode() возвращает значение типа os.FileMode, а os.ModeNamedPipe также имеет тип os.FileMode. Так что это будет тип значения, которое вы хотите напечатать / log.

os.FileMode - это не просто целочисленный тип, это отдельный тип, который реализует fmt.Stringer , И печатая его с помощью глагола %x, правила из пакета делают c:

Если формат (который неявно% v для Println et c .) действительно для строки (% s% q% v% x% X), применяются следующие два правила:

Если в операнде реализован интерфейс ошибок, будет вызван метод Error для преобразования объекта в строку, которая затем будет отформатирована в соответствии с требованиями глагола (если есть).

Если в операнде реализован метод String () string, этот метод будет вызываться для преобразования объекта в строку, которая затем будет отформатирована в соответствии с требованиями глагола (если есть).

Итак, сначала будет вызван метод FileMode.String(), а затем будет напечатано строковое значение с использованием %x, что означает:

String and slice of Bytes ( обрабатывается эквивалентно этими глаголами):

%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)

Он выводит (попробуйте на Go Playground ):

as-is         : 702d2d2d2d2d2d2d2d2d
hexa string   : 702d2d2d2d2d2d2d2d2d
default string: p---------
decimal       : 33554432
hexa          : 2000000
binary        : 10000000000000000000000000
2 голосов
/ 06 февраля 2020

info.Mode() возвращает os.FileMode, который имеет метод String:

https://golang.org/pkg/os/#FileMode .String

Выход String метод выглядит так:

-rw-rw-r--

Когда вы & filemode с именованной маской канала, вы получаете ноль, который равен

----------

, а 2d это -, что объясняет 2d2d2d2d output.

Похоже, что при форматировании для% x printf пытается определить, является ли он одним из распознаваемых типов. Поскольку он не является (FileMode) и имеет метод String (), он сначала преобразует его в строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...