Преобразование произвольного интерфейса Golang в байтовый массив
Я пытаюсь написать хеш, который будет принимать все типы данных. Однажды в функции я обрабатываю данные как массив байтов. У меня возникли проблемы с выяснением того, как передать произвольный interface{}
в массив байтов.
Я попытался использовать двоичный пакет, но он, казалось, зависел от типа переданных данных. Один из параметров Write()
fn (docs) требовал зная порядок байтов параметра.
Все типы данных имеют несколько кратных байту (даже bool), поэтому это должно быть простым в теории.
Код, о котором идет речь ниже,
package bloom
import (
"encoding/gob"
"bytes"
)
// adapted from http://bretmulvey.com/hash/7.html
func ComputeHash(key interface{}) (uint, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(key)
if err != nil {
return 0, err
}
data := buf.Bytes()
var a, b, c uint
a, b = 0x9e3779b9, 0x9e3779b9
c = 0;
i := 0;
for i = 0; i < len(data)-12; {
a += uint(data[i+1] | data[i+2] << 8 | data[i+3] << 16 | data[i+4] << 24)
i += 4
b += uint(data[i+1] | data[i+2] << 8 | data[i+3] << 16 | data[i+4] << 24)
i += 4
c += uint(data[i+1] | data[i+2] << 8 | data[i+3] << 16 | data[i+4] << 24)
a, b, c = mix(a, b, c);
}
c += uint(len(data))
if i < len(data) {
a += uint(data[i])
i++
}
if i < len(data) {
a += uint(data[i] << 8)
i++
}
if i < len(data) {
a += uint(data[i] << 16)
i++
}
if i < len(data) {
a += uint(data[i] << 24)
i++
}
if i < len(data) {
b += uint(data[i])
i++
}
if i < len(data) {
b += uint(data[i] << 8)
i++
}
if i < len(data) {
b += uint(data[i] << 16)
i++
}
if i < len(data) {
b += uint(data[i] << 24)
i++
}
if i < len(data) {
c += uint(data[i] << 8)
i++
}
if i < len(data) {
c += uint(data[i] << 16)
i++
}
if i < len(data) {
c += uint(data[i] << 24)
i++
}
a, b, c = mix(a, b, c)
return c, nil
}
func mix(a, b, c uint) (uint, uint, uint){
a -= b; a -= c; a ^= (c>>13);
b -= c; b -= a; b ^= (a<<8);
c -= a; c -= b; c ^= (b>>13);
a -= b; a -= c; a ^= (c>>12);
b -= c; b -= a; b ^= (a<<16);
c -= a; c -= b; c ^= (b>>5);
a -= b; a -= c; a ^= (c>>3);
b -= c; b -= a; b ^= (a<<10);
c -= a; c -= b; c ^= (b>>15);
return a, b, c
}
Ответы
Ответ 1
Другие проблемы в моем коде привели меня от пакета gob
раньше, оказалось, что это был правильный способ, как предложил @nvcnvn. Релевантный код о том, как решить эту проблему ниже:
package bloom
import (
"encoding/gob"
"bytes"
)
func GetBytes(key interface{}) ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(key)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
Ответ 2
Еще один способ преобразования []bytes
interface{}
в []bytes
- использовать пакет fmt.
/*
* Convert variable 'key' from interface{} to []byte
*/
byteKey := []byte(fmt.Sprintf("%v", key.(interface{})))
fmt.Sprintf преобразует значение интерфейса в строку.
[] Байт преобразует строковое значение в байт.