2014-04-11 63 views
17

Tüm veri türlerini kabul edecek bir karma yazmayı deniyorum. İşlevde bir kez veriyi bayt dizisi olarak ele alırım. Bir bayt dizisine rasgele bir interface{} nasıl yayınlanacağını bulmakta sorun yaşıyorum.Keyfi Golang arabirimini bayt dizisine dönüştürme

İkili paketi kullanmayı denedim, ancak aktarılan veri türüne bağlı görünüyordu. Parametrenin bayt sırasını bilmesi gereken Write() fn (docs) parametrelerinden biri.

Tüm veri türü boyutları bir bayttan (hatta boole) birkaç katıdır, bu nedenle bu, teoride basit olmalıdır. Aşağıda söz konusu

Kod, benim kodunda

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

pkg "kodlama/gob" hakkında nasıl? Kullanabilir misin? – nvcnvn

+0

@nvcnvn, çalışıyor gibi görünüyor. Bunu daha önce denedim ama şimdi küçük değerlerdeki hashta bir zaaf olduğunun farkındayım (0-62 aynıdır?). Çalıştığım aralığı değiştirdim, şimdi çalışıyor gibi görünüyor. Teşekkürler! –

+0

hataları düzeltin, burada bulunan güncellenmiş kod: https://gist.github.com/natebrennand/10442587 –

cevap

40

Diğer sorunlar uzakta gob paket önceki götürdü, o @nvcnvn önerildiği gibi uygun bir yol olduğunu ortaya çıktı. Aşağıdaki bu sorunu çözmek için ilgili kod:

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

Sorunuzun cevabı olarak kendi cevabınızı kabul etmekten çekinmeyin :) – photoionized

+0

Bu bir ve tam tersi: https://play.golang.org/p/mJPMN1_KSv – sromku

+1

Bu yöntemin kullanımını gösteren bir örneğe sahip olmak güzel olurdu. Go ile benim gibi yeni başlayanlar için gerçekten çok yardımcı olacaktır! –

İlgili konular