web-dev-qa-db-ja.com

任意のGolangインターフェイスをバイト配列に変換します

すべてのデータ型を受け入れるハッシュを作成しようとしています。関数に入ったら、データをバイト配列として処理します。任意の_interface{}_をバイト配列にキャストする方法を見つけるのに問題があります。

バイナリパッケージを使用してみましたが、渡されたデータの種類に依存するようです。Write() fn (docs) のパラメーターの1つは、パラメータ。

データ型のサイズはすべてバイトの倍数であるため(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
}
_
25
Nate Brennand

私のコードの他の問題により、以前に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
}
57
Nate Brennand

interface{}[]bytesに変換する別の方法は、fmtパッケージを使用することです。

/*
* Convert variable `key` from interface{} to []byte
*/

byteKey := []byte(fmt.Sprintf("%v", key.(interface{})))

fmt.Sprintfは、インターフェイス値を文字列に変換します。
[] byteは文字列値をバイトに変換します。

1
Midori