18

Interface{} をフィールドとして含む構造体を逆エンコードしてエンコードしようとしています。

問題は、エンコーディングが正常に機能することですが、データをdata値にデコードしようとすると{ <nil>}.

Data interface{}に変更すると実際には機能Data substringしますが、クエリに応じて異なるタイプのデータベースにクエリの結果をキャッシュしたいので、これは私にとっては解決策ではありません。(例:UsersまたはCookies)

最小限の作業例

ソース

http://play.golang.org/p/aX7MIfqrWl

package main

import (
    "bytes"
    "encoding/gob"
    "fmt"
)

type Data struct {
    Name string
    Data interface{}
}

type SubType struct {
    Foo string
}

func main() {
    // Encode
    encodeData := Data{
        Name: "FooBar",
        Data: SubType{Foo: "Test"},
    }
    mCache := new(bytes.Buffer)
    encCache := gob.NewEncoder(mCache)
    encCache.Encode(encodeData)

    fmt.Printf("Encoded: ")
    fmt.Println(mCache.Bytes())

    // Decode
    var data Data
    pCache := bytes.NewBuffer(mCache.Bytes())
    decCache := gob.NewDecoder(pCache)
    decCache.Decode(&data)

    fmt.Printf("Decoded: ")
    fmt.Println(data)
}

出力

期待される出力

エンコード: [37 255 129 3 1 1 4 68 97 116 97 1 255 130 0 1 2 1 4 78 97 109 101 1 12 0 1 4 68 97 116 97 1 255 132 0 0 0 29 255 131 7 8 3 1 11 98 84 121 112 101 1 255 132 0 1 1 1 3 70 111 111 1 12 0 0 0 19 255 130 1 6 70 111 111 66 97 114 1 1 4 84 101 115 116 0 0]

デコード: {FooBar {Test}}

現在の結果

エンコード: [37 255 129 3 1 1 4 68 97 116 97 1 255 130 0 1 2 1 4 78 97 109 101 1 12 0 1 4 68 97 116 97 1 255 132 0 0 0 29 255 131 7 8 3 1 11 98 84 121 112 101 1 255 132 0 1 1 1 3 70 111 111 1 12 0 0 0 19 255 130 1 6 70 111 111 66 97 114 1 1 4 84 101 115 116 0 0]

デコード: { }

4

2 に答える 2

44

問題は、コードで実行時にエラーが発生することですencCache.Encode(encodeData)が、エラーをチェックしていないため、それを認識していません。encodedData が適切にエンコードされないため、出力は空白になります。

エラーチェックを追加すると、

err := enc.Encode(encodeData)
if err != nil {
    log.Fatal("encode error:", err)
}

次に、次のようなものが表示されます

2013/03/09 17:57:23 encode error:gob: type not registered for interface: main.SubType

enc.Encode(encodeData) の前に元のコードに 1 行追加すると、

gob.Register(SubType{})

次に、期待される出力が得られます。

Decoded: {FooBar {Test}}

http://play.golang.org/p/xt4zNyPZ2Wを参照

于 2013-03-09T23:06:01.150 に答える
-6

デコーダーにはフィールドのタイプを判別する方法がないため、インターフェースにデコードすることはできません。

これは、いくつかの異なる方法で処理できます。1つは、デコード可能なすべてのタイプのフィールドを持つ構造体をDataに保持させることです。しかし、タイプは非常に複雑になる可能性があります。

もう1つの方法は、構造体にGobDecoderおよびGobEncoderインターフェースを実装し、型に独自のシリアル化を実装することです。しかし、これはおそらく理想的ではありません。

おそらく最善のアプローチは、代わりに特定のタイプをキャッシュに保存し、タイプごとに別々の方法を使用することです。あなたの例を使用するには。アプリケーションには、キャッシュで呼び出されるキャッシュメソッドがありGetSubType(key string) (*SubType, error)ます。これにより、インターフェイスの代わりに具象型またはデコードエラーが返されます。よりクリーンで読みやすく、タイプセーフになります。

于 2013-01-02T19:05:53.247 に答える