Upgrade to Pro — share decks privately, control downloads, hide ads and more …

今更だけどGob

 今更だけどGob

Jun 21 2017 CA.go

Shun Kokubo

June 22, 2017
Tweet

Other Decks in Technology

Transcript

  1. KVS? File? // bolt/boltdb db.Update(func(tx *bolt.Tx) error { b :=

    tx.Bucket([]byte("anyBucket")) err := b.Put([]byte("key"), []byte("value")) return nil }) // syndtr/goleveldb err = db.Put([]byte("key"), []byte("value"), nil) // allegro/bigcache cache.Set("key", []byte("value")) そこでGob
  2. 使い方 var buf bytes.Buffer enc := gob.NewEncoder(&buf) dec := gob.NewDecoder(&buf)

    e := Data{ ID: "test_id", Num: 100, } var d Data enc.Encode(e) dec.Decode(&d) fmt.Printf("%+v", d) Run
  3. 使い方 var buf bytes.Buffer enc := gob.NewEncoder(&buf) dec := gob.NewDecoder(&buf)

    var e int e = 100 var d int enc.Encode(e) dec.Decode(&d) fmt.Println(d) Run
  4. 定義不要 type wireType struct { ArrayT *arrayType SliceT *sliceType StructT

    *structType MapT *mapType GobEncoderT *gobEncoderType BinaryMarshalerT *gobEncoderType TextMarshalerT *gobEncoderType }
  5. 定義不要 type CommonType struct { Name string Id int }

    type arrayType struct { CommonType Elem typeId Len int } type sliceType struct { CommonType Elem typeId } type structType struct { CommonType Field []*fieldType } type fieldType struct { Name string Id int } 全てName とID を持つCommonType を埋め込みで持つ
  6. Self describing type Example struct { ID string Num int

    Value interface{} } Example というType を定義すると binary に定義情報が含まれる ("define type id" 256, definition of type Example)(256, Example value)...
  7. Self describing 実際のbinary もこの様な形となる $ hexdump -C example.bin 00000000 2e

    ff 81 03 01 01 07 45 78 61 6d 70 6c 65 01 ff |.......Example..| 00000010 82 00 01 03 01 02 49 44 01 0c 00 01 03 4e 75 6d |......ID.....Num| 00000020 01 04 00 01 05 56 61 6c 75 65 01 10 00 00 00 22 |.....Value....."| 00000030 ff 82 01 0a 65 78 61 6d 70 6c 65 5f 69 64 01 ff |....example_id..| 00000040 c8 01 06 73 74 72 69 6e 67 0c 06 00 04 74 65 73 |...string....tes| 00000050 74 00 |t.| 00000052 CommonType を含むwireType によって表現される 各type のID と eld 情報
  8. 構造変更が可能 type Src struct { ID string Score float64 Num

    int } type Dest struct { ID *string Score float32 Order int } encode,decode 側のtype, eld が違っても
  9. 構造変更が可能 値の扱われ方に特徴がある var buf bytes.Buffer enc := gob.NewEncoder(&buf) dec :=

    gob.NewDecoder(&buf) s := Src{ ID: "test_id", Num: 100, Score: 1.23, } var d Dest enc.Encode(s) dec.Decode(&d) fmt.Printf("%+v\n", d) fmt.Println(*d.ID) Run
  10. ベンチで比較 type Data struct { Str string Int int64 Float

    float64 Bool bool } type Encoder interface { Encode(interface{}) error } type Decoder interface { Decode(interface{}) error }
  11. ベンチで比較 func benchEncode(buf *bytes.Buffer, enc Encoder, b *testing.B) { b.ResetTimer()

    for i := 0; i < b.N; i++ { buf.Reset() err := enc.Encode(encodeData) if err != nil { b.Fatal(err) } } }
  12. ベンチで比較 func benchDecode(buf *bytes.Buffer, enc Encoder, dec Decoder, b *testing.B)

    { var e Data b.ResetTimer() for i := 0; i < b.N; i++ { b.StopTimer() buf.Reset() err := enc.Encode(encodeData) if err != nil { b.Fatal(err) } b.StartTimer() err = dec.Decode(&e) if err != nil { b.Fatal(err) } } }
  13. ベンチで比較 func BenchmarkGobEncode(b *testing.B) { var buf bytes.Buffer enc :=

    gob.NewEncoder(&buf) benchEncode(&buf, enc, b) } func BenchmarkJsonEncode(b *testing.B) { var buf bytes.Buffer enc := json.NewEncoder(&buf) benchEncode(&buf, enc, b) }
  14. ベンチで比較 func BenchmarkGobDecode(b *testing.B) { var buf bytes.Buffer enc :=

    gob.NewEncoder(&buf) dec := gob.NewDecoder(&buf) benchDecode(&buf, enc, dec, b) } func BenchmarkJsonDecode(b *testing.B) { var buf bytes.Buffer enc := json.NewEncoder(&buf) dec := json.NewDecoder(&buf) benchDecode(&buf, enc, dec, b) }
  15. ベンチで比較 $ go test -benchmem -bench . BenchmarkGobEncode-8 2000000 642

    ns/op 48 B/op 1 allocs/op BenchmarkJsonEncode-8 2000000 946 ns/op 56 B/op 2 allocs/op BenchmarkGobDecode-8 1000000 1425 ns/op 16 B/op 1 allocs/op BenchmarkJsonDecode-8 500000 3299 ns/op 48 B/op 3 allocs/op
  16. 注意点 interface を扱う時は… type Handler interface { GetID() string }

    type A struct { ID string } func (a *A) GetID() string { return a.ID }
  17. 注意点 最初にRegister func main() { var buf bytes.Buffer enc :=

    gob.NewEncoder(&buf) dec := gob.NewDecoder(&buf) var e Handler e = &A{ ID: "A", } fmt.Println(enc.Encode(&e)) var d Handler fmt.Println(dec.Decode(&d)) fmt.Println(d.GetID()) } Run
  18. 注意点 ポインターで渡す func init() { gob.Register(&A{}) } func main() {

    var buf bytes.Buffer enc := gob.NewEncoder(&buf) dec := gob.NewDecoder(&buf) var e Handler e = &A{ ID: "A", } fmt.Println(enc.Encode(e)) var d Handler fmt.Println(dec.Decode(&d)) fmt.Println(d.GetID()) } Run
  19. 注意点 func init() { gob.Register(&A{}) } func main() { var

    buf bytes.Buffer enc := gob.NewEncoder(&buf) dec := gob.NewDecoder(&buf) var e Handler e = &A{ ID: "A", } fmt.Println(enc.Encode(&e)) var d Handler fmt.Println(dec.Decode(&d)) fmt.Println(d.GetID()) } Run