2014-04-11 15 views
17

Sto provando a scrivere un hash che accetterà tutti i tipi di dati. Una volta nella funzione, gestisco i dati come una matrice di byte. Ho difficoltà a capire come lanciare un arbitrario interface{} in un array di byte.Convertire l'interfaccia arbitraria Golang nell'array di byte

Ho provato utilizzando il pacchetto binario ma sembrava dipendere dal tipo di dati passati. Uno dei parametri del Write() fn (docs) necessario conoscere l'ordine dei byte del parametro.

Tutte le dimensioni dei tipi di dati sono alcune multiple di un byte (anche il valore bool), quindi in teoria dovrebbe essere semplice.

codice in questione qui di seguito,

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 
} 
+3

Come su pkg "encoding/gob"? Puoi usarlo? – nvcnvn

+0

@nvcnvn, sembra funzionare. L'ho provato prima, ma ora capisco che c'è un punto debole nell'hash su valori piccoli (0-62 sono identici?). Ho cambiato la gamma che stavo lavorando con qualsiasi ora sembra funzionare. Grazie! –

+0

corretto gli errori nella hash fn, codice aggiornato trovato qui: https://gist.github.com/natebrennand/10442587 –

risposta

40

Altri problemi nel mio codice mi ha portato via dal pacchetto gob in precedenza, scopre che era il modo corretto come @nvcnvn suggerito. Codice in materia su come risolvere questo problema di seguito:

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 
} 
+0

Sentiti libero di accettare la tua risposta come risposta alla tua domanda :) – photoionized

+0

Questo e viceversa: https://play.golang.org/p/mJPMN1_KSv – sromku

+1

Sarebbe bello avere un esempio che mostra l'utilizzo di questo metodo. Per molti principianti come me con Go, sarebbe davvero utile assegnare! –