Как копировать из слайса в массив с поиском на слайс - PullRequest
0 голосов
/ 22 ноября 2018

Я пишу библиотеку для работы с двоичным форматом.

У меня есть структура с массивами vars, которую я хотел бы сохранить для целей документации.

Мне нужно такжеискать и сообщать из входного среза байтов.

Какой-то псевдокод:

type foo struct {
    boo [5]byte
    coo [3]byte
}

func main() {

    // input is a []byte full of datas, read from a file

    var bar foo

    // Here i need something that writes 5 bytes to bar.foo from input
    bar.foo = somefunc(input, numberOfFoo) // ???
    // I need also tell() and seek()
    input.seek(n)

}

Как это сделать с помощью одной функции?

1 Ответ

0 голосов
/ 22 ноября 2018

Работа на входе байтового слайса

Вы можете использовать встроенный copy() для копирования байтов из исходного слайса в место назначения.Если у вас есть массив, нарежьте его, чтобы получить срез, например bar.boo[:].Для поиска просто используйте другое смещение в исходном срезе, также путем его изменения, например, input[startPos:].

Например:

input := []byte{1, 2, 3, 4, 5, 0, 0, 8, 9, 10}

var bar foo
copy(bar.boo[:], input)

// Skip 2 bytes, seek to the 8th byte:
input = input[7:]

copy(bar.coo[:], input)

fmt.Printf("%+v", bar)

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

{boo:[1 2 3 4 5] coo:[8 9 10]}

Создание ReadSeeker

Другой вариант заключается в переносе входного байтового фрагмента в io.ReadSeeker, например bytes.Reader, затем вы можете читать с него.

Например:

input := []byte{1, 2, 3, 4, 5, 0, 0, 8, 9, 10}
r := bytes.NewReader(input)

var bar foo
if _, err := io.ReadFull(r, bar.boo[:]); err != nil {
    panic(err)
}

// Skip 2 bytes, seek to the 8th byte:
if _, err := r.Seek(7, io.SeekStart); err != nil {
    panic(err)
}

if _, err := io.ReadFull(r, bar.coo[:]); err != nil {
    panic(err)
}

fmt.Printf("%+v", bar)

Вывод такой же, попробуйте на Go Playground .

Использование encoding/binary

Еще одним решением будет использование encoding/binary для чтения всей структуры за один шаг.

InЧтобы сделать это, нам нужно экспортировать поля, и мы должны вставить анонимное или пустое поле, которое охватывает пропущенные байты:

type foo struct {
    Boo [5]byte
    _   [2]byte // don't care
    Coo [3]byte
}

Имея вышеуказанный тип, мы можем прочитать все это в одномшаг, подобный следующему:

input := []byte{1, 2, 3, 4, 5, 0, 0, 8, 9, 10}
r := bytes.NewReader(input)

var bar foo
if err := binary.Read(r, binary.LittleEndian, &bar); err != nil {
    panic(err)
}

fmt.Printf("%+v", bar)

Вывод аналогичен, за исключением того, что он также отображает анонимное поле (попробуйте на Go Playground ):

{Boo:[1 2 3 4 5] _:[0 0] Coo:[8 9 10]}

См.связанный ответ: Зачем использовать массивы вместо слайсов?

Чтение непосредственно из исходного файла

Вы упомянули, что ваш input фрагмент - это чтение файла.Обратите внимание, что вам не нужно читать файл ранее, так как os.File реализует io.Reader, даже io.ReadSeeker, что означает, что вы можете читать из него напрямую, см. Создание раздела ReadSeeker.Вы также можете напрямую применить решение encoding/binary, поскольку в этом решении мы также использовали ридер.

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