2016-06-22 25 views
1

我需要但使用gob編碼一些數據,我發現「類型的無」不能正確處理(去1.6.2)採空區嘗試解碼在EOF誤差零值結果

https://play.golang.org/p/faypK8uobF

package main 

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

type T struct { 
    A int 
} 

func init() { 
    gob.Register(map[string]interface{}{}) 
    gob.Register(new(T)) 
} 
func main() { 
    bys := bytes.NewBuffer(nil) 
    gob.NewEncoder(bys).Encode(map[string]interface{}{ 
     "v": (*T)(nil), 
    }) 
    out := map[string]interface{}{} 
    if err := gob.NewDecoder(bys).Decode(&out); err != nil { 
     log.Panic(err) 
    } 
    return 
} 

輸出:

panic: EOF 

回答

4

你吞嚥通過Encoder.Encode()返回error

err := gob.NewEncoder(bys).Encode(map[string]interface{}{ 
    "v": (*T)(nil), 
}) 
if err != nil { 
    fmt.Println(err) 
} 

輸出:

gob: gob: cannot encode nil pointer of type *main.T inside interface 

這是通過未導出方法Encoder.encodeInterface()生成。從encode.go,未導出的方法Encoder.encodeInterface()報價:

// Gobs can encode nil interface values but not typed interface 
// values holding nil pointers, since nil pointers point to no value. 
elem := iv.Elem() 
if elem.Kind() == reflect.Ptr && elem.IsNil() { 
    errorf("gob: cannot encode nil pointer of type %s inside interface", iv.Elem().Type()) 
} 

所以你Encoder.Encode()失敗,它沒有寫入到輸出(這是bys緩存),所以試圖讀取(解碼)從東西它導致EOF。

但是,爲什麼你不能編碼一個interface{}價值持有nil指針?從包裝文檔引用encoding/gob

指針不傳輸,但它們指向的內容被傳輸;也就是說,這些值是平坦的。

interface{}包含指針類型的值,但指針nil,它指向什麼,它不能被夷爲平地。


這裏是在github一個相關的問題:encoding/gob: panic on encoding nil pointer #3704

拉斯:

採空區不知道指針是什麼:一切都被夷爲平地。在接口{}中放置一個零指針會創建一個gob無法發送的非零值(它不是nil接口)(它不能表示'nil指針')。

羅布·派克:

正確的。只有具體值本身是可傳輸的,才能傳輸接口值。至少現在,這相當於說,無法發送保存鍵入nil指針的接口。

+0

非常感謝你,很好的詳細信息。 – llx