2013-06-02 4 views
26

У меня есть функция, которая получает []byte, но я у меня есть int, что является лучшим способом для этого преобразования?Преобразование целого числа в массив байтов

err = a.Write([]byte(myInt)) 

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

ответ

27

Я согласен с подходом BrainStorm не в: если предположить, что вы передаете машину дружественный бинарное представление, используйте encoding/binary библиотеку. OP предполагает, что binary.Write() может иметь некоторые накладные расходы. Рассматривая the source для реализации Write(), я вижу, что он принимает некоторые решения во время выполнения для максимальной гибкости.

189 func Write(w io.Writer, order ByteOrder, data interface{}) error { 
    190  // Fast path for basic types. 
    191  var b [8]byte 
    192  var bs []byte 
    193  switch v := data.(type) { 
    194  case *int8: 
    195   bs = b[:1] 
    196   b[0] = byte(*v) 
    197  case int8: 
    198   bs = b[:1] 
    199   b[0] = byte(v) 
    200  case *uint8: 
    201   bs = b[:1] 
    202   b[0] = *v 
    ... 

Справа? Write() принимает очень общий третий аргумент data, и это накладывает некоторые накладные расходы, так как время выполнения Go принудительно вводится в информацию типа кодирования. Так как Write() принимает здесь несколько решений, которые вам просто не нужны в вашей ситуации, возможно, вы можете просто напрямую вызвать функции кодирования и посмотреть, работает ли он лучше.

Что-то вроде этого:

package main 

import (
    "encoding/binary" 
    "fmt" 
) 

func main() { 
    bs := make([]byte, 4) 
    binary.LittleEndian.PutUint32(bs, 31415926) 
    fmt.Println(bs) 
} 

Дайте нам знать, как это работает.

В противном случае, если вы просто пытаетесь получить представление ASCII целого числа, вы можете получить строковое представление (возможно, с strconv.Itoa) и передать эту строку в тип []byte.

package main 

import (
    "fmt" 
    "strconv" 
) 

func main() { 
    bs := []byte(strconv.Itoa(31415926)) 
    fmt.Println(bs) 
} 
+0

Закончено с использованием небольшого варианта вашего первого предложения. Должен был погрузиться в реализацию сам, спасибо за подсказку. – vascop

20

Проверьте пакет «кодирование/бинарный». В частности, функции чтения и записи:

binary.Write(a, binary.LittleEndian, myInt) 
+3

После бенчмаркинг «enconding/двоичный» путь, он занимает почти в 4 раза больше, чем Int -> строка -> байты – vascop

+3

Но что байты представления действительно ожидать, что ваш потребитель для целых чисел? Наверное, не ASCII-представление? Просьба уточнить. – dyoo

+0

@vascop он делает. Но 'binary.LittleEndian.PutUint64 (bs, value)' намного быстрее, чем int -> string -> byte. –

8

Извините, это может быть немного запоздало. Но я думаю, что нашел лучшую реализацию в go docs.

buf := new(bytes.Buffer) 
var num uint16 = 1234 
err := binary.Write(buf, binary.LittleEndian, num) 
if err != nil { 
    fmt.Println("binary.Write failed:", err) 
} 
fmt.Printf("% x", buf.Bytes()) 
Смежные вопросы