?
このドキュメントでは、 php中國(guó)語(yǔ)ネットマニュアル リリース
import "encoding/gob"
Overview
Index
Examples
Package gob管理gobs流 - 在編碼器(發(fā)送器)和解碼器(接收器)之間交換的二進(jìn)制值。一個(gè)典型的用途是傳輸遠(yuǎn)程過(guò)程調(diào)用(RPC)的參數(shù)和結(jié)果,如由“net / rpc”包提供的那些。
該實(shí)現(xiàn)為流中的每種數(shù)據(jù)類型編譯自定義編解碼器,并且在使用單個(gè)編碼器傳輸值流時(shí)緩解編譯成本,效率最高。
gob是自我描述的。流中的每個(gè)數(shù)據(jù)項(xiàng)都有一個(gè)類型的規(guī)范,用一組預(yù)定義的類型表示。指針不傳輸,但它們指向的內(nèi)容被傳送; 也就是說(shuō),這些值是平坦的。無(wú)指針是不允許的,因?yàn)樗鼈儧](méi)有價(jià)值。遞歸類型工作正常,但遞歸值(帶周期的數(shù)據(jù))是有問(wèn)題的。這可能會(huì)改變。
要使用gobs,請(qǐng)創(chuàng)建一個(gè)編碼器,并將其與一系列數(shù)據(jù)項(xiàng)一起呈現(xiàn)為值或地址,這些值可以取消引用值。編碼器確保在需要之前發(fā)送所有類型的信息。在接收端,解碼器從編碼流中檢索值并將它們解壓縮成局部變量。
源和目標(biāo)值/類型不需要完全對(duì)應(yīng)。對(duì)于結(jié)構(gòu)體來(lái)說(shuō),源中但沒(méi)有接收變量的域(由名稱標(biāo)識(shí))將被忽略。在接收變量中但從傳輸類型或值中缺失的字段將在目標(biāo)中被忽略。如果同時(shí)存在兩個(gè)同名的字段,則其類型必須兼容。接收器和發(fā)射器都將執(zhí)行所有必要的間接和取消引用,以在gob和實(shí)際Go值之間進(jìn)行轉(zhuǎn)換。例如,示意性的采空區(qū)類型,
struct { A, B int }
可以從以下任何一種Go類型發(fā)送或接收:
struct { A, B int }// the same*struct { A, B int }// extra indirection of the structstruct { *A, **B int }// extra indirection of the fieldsstruct { A, B int64 }// different concrete value type; see below
它也可以被接收到以下任何一個(gè)中:
struct { A, B int }// the samestruct { B, A int }// ordering doesn't matter; matching is by namestruct { A, B, C int }// extra field (C) ignoredstruct { B int }// missing field (A) ignored; data will be droppedstruct { B, C int }// missing field (A) ignored; extra field (C) ignored.
嘗試接收這些類型將導(dǎo)致解碼錯(cuò)誤:
struct { A int; B uint }// change of signedness for Bstruct { A int; B float }// change of type for Bstruct { }// no field names in commonstruct { C, D int }// no field names in common
整數(shù)以兩種方式傳輸:任意精度有符號(hào)整數(shù)或任意精度無(wú)符號(hào)整數(shù)。gob格式中沒(méi)有int8,int16等歧視; 只有有符號(hào)和無(wú)符號(hào)的整數(shù)。如下所述,發(fā)送器以可變長(zhǎng)度編碼發(fā)送值; 接收器接受該值并將其存儲(chǔ)在目標(biāo)變量中。浮點(diǎn)數(shù)總是使用IEEE-754 64位精度發(fā)送(見(jiàn)下文)。
帶符號(hào)的整數(shù)可以接收到任何有符號(hào)的整數(shù)變量中:int,int16等; 無(wú)符號(hào)整數(shù)可以接收到任何無(wú)符號(hào)整數(shù)變量中; 并且可以將浮點(diǎn)值接收到任何浮點(diǎn)變量中。但是,目標(biāo)變量必須能夠表示值,否則解碼操作將失敗。
結(jié)構(gòu),數(shù)組和片也被支持。結(jié)構(gòu)僅對(duì)導(dǎo)出的字段進(jìn)行編碼和解碼。字符串和字節(jié)數(shù)組以特殊的高效表示形式提供支持(請(qǐng)參見(jiàn)下文)。當(dāng)一個(gè)片段被解碼時(shí),如果現(xiàn)有片段具有容量,片段將被擴(kuò)展到位; 如果不是,則分配一個(gè)新數(shù)組。無(wú)論如何,結(jié)果切片的長(zhǎng)度報(bào)告解碼的元素的數(shù)量。
通常,如果需要分配,解碼器將分配內(nèi)存。如果不是,它將使用從流中讀取的值更新目標(biāo)變量。它不會(huì)首先初始化它們,因此如果目標(biāo)是復(fù)合值(如地圖,結(jié)構(gòu)或切片),則解碼值將按照元素方式合并到現(xiàn)有變量中。
功能和頻道不會(huì)以采空區(qū)發(fā)送。試圖在頂層編碼這樣的值將會(huì)失敗。chan或func類型的struct字段被視為完全像未導(dǎo)出的字段,并被忽略。
Gob可以按照優(yōu)先順序調(diào)用相應(yīng)的方法來(lái)編碼實(shí)現(xiàn)GobEncoder或encoding.BinaryMarshaler接口的任何類型的值。
Gob可以通過(guò)調(diào)用相應(yīng)的方法來(lái)解碼實(shí)現(xiàn)GobDecoder或編碼的任何類型的值.BinaryUnmarshaler接口也會(huì)按照該優(yōu)先順序再次進(jìn)行解碼。
本節(jié)介紹編碼,對(duì)大多數(shù)用戶不重要的詳細(xì)信息。細(xì)節(jié)從下到上呈現(xiàn)。
無(wú)符號(hào)整數(shù)以兩種方式之一發(fā)送。如果它小于128,則將其作為具有該值的字節(jié)發(fā)送。否則,它將作為保留該值的最小長(zhǎng)度的大端(高字節(jié)的第一個(gè))字節(jié)流發(fā)送,前面是一個(gè)保存字節(jié)計(jì)數(shù)的字節(jié),取反。因此,0發(fā)送為,7發(fā)送為(07),256發(fā)送為 (FE 01 00)。
布爾值在無(wú)符號(hào)整數(shù)內(nèi)編碼:0代表假,1代表真。
一個(gè)有符號(hào)整數(shù)i被編碼在一個(gè)無(wú)符號(hào)整數(shù)u中。在u中,位1向上包含該值; 位0表示它們是否應(yīng)該在收到時(shí)補(bǔ)充。編碼算法如下所示:
var u uintif i < 0 { u = (^uint(i) << 1) | 1 // 補(bǔ)充 i, 位0是1} else { u = (uint(i) << 1) // 不補(bǔ)充 i, 位0是0}encodeUnsigned(u)
低位因此類似于符號(hào)位,但是使其成為補(bǔ)碼位而不是保證最大的負(fù)整數(shù)不是特例。例如,-129=^128=(^256>>1)編碼為(FE 01 01)。
浮點(diǎn)數(shù)字總是作為float64值的表示形式發(fā)送。該值使用math.Float64bits轉(zhuǎn)換為uint64。uint64然后被字節(jié)反轉(zhuǎn)并作為常規(guī)無(wú)符號(hào)整數(shù)發(fā)送。字節(jié)反轉(zhuǎn)意味著尾數(shù)的指數(shù)和高精度部分先行。由于低位通常為零,因此可以節(jié)省編碼字節(jié)。例如,17.0只用三個(gè)字節(jié)編碼 (FE 31 40)。
字符串和字節(jié)片段作為無(wú)符號(hào)計(jì)數(shù)發(fā)送,然后是該值的許多未解釋的字節(jié)。
所有其他切片和數(shù)組都作為無(wú)符號(hào)計(jì)數(shù)發(fā)送,然后遞歸地使用標(biāo)準(zhǔn)采樣編碼作為其類型。
地圖是作為無(wú)符號(hào)計(jì)數(shù)發(fā)送的,然后是許多鍵元素對(duì)??盏牡橇愕牡貓D被發(fā)送,所以如果接收方還沒(méi)有分配一個(gè)地圖,則一直會(huì)在接收時(shí)分配一個(gè)地圖,除非傳輸?shù)牡貓D是零而不是在頂層。
在切片和陣列以及地圖中,即使所有元素均為零,也會(huì)傳輸所有元素,即使是零值元素。
結(jié)構(gòu)以(字段號(hào),字段值)對(duì)的序列發(fā)送。字段值是使用遞歸的類型的標(biāo)準(zhǔn)gob編碼發(fā)送的。如果某個(gè)字段的類型為零(數(shù)組除外;請(qǐng)參見(jiàn)上文),則該字段在傳輸中將被忽略。字段編號(hào)由編碼結(jié)構(gòu)的類型定義:編碼類型的第一個(gè)字段是字段0,第二個(gè)字段是字段1等。編碼值時(shí),字段編號(hào)為delta編碼以提高效率,字段始終按照增加字段的順序發(fā)送; 三角洲因此沒(méi)有簽名。增量編碼的初始化將字段編號(hào)設(shè)置為-1,因此具有值7的無(wú)符號(hào)整數(shù)字段0作為無(wú)符號(hào)的增量= 1,無(wú)符號(hào)的值= 7或(01 07)發(fā)送。最后,在所有字段發(fā)送之后,終止標(biāo)記表示結(jié)構(gòu)的結(jié)束。
接口類型不檢查兼容性; 所有接口類型都作為單個(gè)“接口”類型的成員進(jìn)行處理,類似于int或[] byte - 實(shí)際上它們都被視為interface {}。接口值以字符串的形式傳輸,標(biāo)識(shí)發(fā)送的具體類型(必須通過(guò)調(diào)用寄存器預(yù)先定義的名稱),然后是以下數(shù)據(jù)長(zhǎng)度的字節(jié)數(shù)(因此,如果不能存儲(chǔ)),然后是存儲(chǔ)在接口值中的具體(動(dòng)態(tài))值的通常編碼。(一個(gè)零接口值由空字符串標(biāo)識(shí)并且不傳送任何值。)一旦收到,解碼器就會(huì)驗(yàn)證解包后的具體項(xiàng)目是否滿足接收變量的接口。
如果一個(gè)值傳遞給Encode,并且該類型不是一個(gè)結(jié)構(gòu)體(或指向結(jié)構(gòu)體的指針等),為了簡(jiǎn)化處理,它被表示為一個(gè)字段的結(jié)構(gòu)。這樣做的唯一可見(jiàn)效果是在值之后編碼一個(gè)零字節(jié),就像編碼結(jié)構(gòu)的最后一個(gè)字段之后一樣,以便解碼算法知道頂級(jí)值何時(shí)完成。
類型的表示如下所述。當(dāng)在編碼器和解碼器之間的給定連接上定義類型時(shí),它被分配一個(gè)有符號(hào)的整數(shù)類型ID。當(dāng)調(diào)用Encoder.Encode(v)時(shí),它確保為v及其所有元素的類型分配一個(gè)id,然后發(fā)送該對(duì) (typeid, encoded-v),其中typeid是編碼類型的類型id v和encoded-v是值v的gob編碼。
為了定義一個(gè)類型,編碼器選擇一個(gè)未使用的肯定類型id,并發(fā)送這個(gè)對(duì)(-type id, encoded-type),其中encoded-type是wireType描述的gob編碼,由以下類型構(gòu)造而成:
type wireType struct { ArrayT *ArrayType SliceT *SliceType StructT *StructType MapT *MapType}type arrayType struct { CommonType Elem typeId Len int}type CommonType struct { Name string // the name of the struct type Id int // the id of the type, repeated so it's inside the type}type sliceType struct { CommonType Elem typeId}type structType struct { CommonType Field []*fieldType // the fields of the struct.}type fieldType struct { Name string // the name of the field. Id int // the type id of the field, which must be already defined}type mapType struct { CommonType Key typeId Elem typeId}
如果存在嵌套類型標(biāo)識(shí),則必須在使用頂級(jí)類型標(biāo)識(shí)描述encoded-v之前定義所有內(nèi)部類型標(biāo)識(shí)的類型。
為了簡(jiǎn)化設(shè)置,連接被定義為先驗(yàn)地理解這些類型,以及基本采樣類型int,uint等。它們的ID是:
bool 1int 2uint 3float 4[]byte 5string 6complex 7interface 8// gap for reserved ids.WireType 16ArrayType 17CommonType 18SliceType 19StructType 20FieldType 21// 22 is slice of fieldType.MapType 23
最后,通過(guò)對(duì)Encode的調(diào)用創(chuàng)建的每條消息前面都有一個(gè)編碼的無(wú)符號(hào)整數(shù)數(shù)量,該數(shù)量是消息中剩余的字節(jié)數(shù)。在初始類型名稱之后,接口值以相同方式包裝; 實(shí)際上,接口值的作用類似于Encode的遞歸調(diào)用。
總之,一個(gè)gob流看起來(lái)像
(byteCount (-type id, encoding of a wireType)* (type id, encoding of a value))*
其中*表示重復(fù)次數(shù)為零或更多,并且值的類型ID必須預(yù)先定義或在流中的值之前定義。
兼容性:對(duì)軟件包的未來(lái)更改將盡力保持與使用先前版本編碼的流的兼容性。也就是說(shuō),這個(gè)軟件包的任何發(fā)布版本都應(yīng)該能夠解碼使用任何以前發(fā)布的版本編寫的數(shù)據(jù),并受到諸如安全修復(fù)等問(wèn)題的影響。有關(guān)背景信息,請(qǐng)參閱Go兼容性文檔:https://golang.org/doc/go1compat
關(guān)于gob線格式的設(shè)計(jì)討論,請(qǐng)參閱“數(shù)據(jù)采集”:https://blog.golang.org/gobs-of-data
這個(gè)例子顯示了軟件包的基本用法:創(chuàng)建一個(gè)編碼器,傳輸一些值,用解碼器接收它們。
package mainimport ("bytes""encoding/gob""fmt""log")type P struct { X, Y, Z int Name string}type Q struct { X, Y *int32 Name string}// This example shows the basic usage of the package: Create an encoder,// transmit some values, receive them with a decoder.func main() {// Initialize the encoder and decoder. Normally enc and dec would be// bound to network connections and the encoder and decoder would// run in different processes.var network bytes.Buffer // Stand-in for a network connection enc := gob.NewEncoder(&network) // Will write to network. dec := gob.NewDecoder(&network) // Will read from network.// Encode (send) some values. err := enc.Encode(P{3, 4, 5, "Pythagoras"})if err != nil { log.Fatal("encode error:", err)} err = enc.Encode(P{1782, 1841, 1922, "Treehouse"})if err != nil { log.Fatal("encode error:", err)}// Decode (receive) and print the values.var q Q err = dec.Decode(&q)if err != nil { log.Fatal("decode error 1:", err)} fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y) err = dec.Decode(&q)if err != nil { log.Fatal("decode error 2:", err)} fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y)}
本示例傳輸一個(gè)實(shí)現(xiàn)自定義編碼和解碼方法的值。
package mainimport ("bytes""encoding/gob""fmt""log")// The Vector type has unexported fields, which the package cannot access.// We therefore write a BinaryMarshal/BinaryUnmarshal method pair to allow us// to send and receive the type with the gob package. These interfaces are// defined in the "encoding" package.// We could equivalently use the locally defined GobEncode/GobDecoder// interfaces.type Vector struct { x, y, z int}func (v Vector) MarshalBinary() ([]byte, error) {// A simple encoding: plain text.var b bytes.Buffer fmt.Fprintln(&b, v.x, v.y, v.z)return b.Bytes(), nil}// UnmarshalBinary modifies the receiver so it must take a pointer receiver.func (v *Vector) UnmarshalBinary(data []byte) error {// A simple encoding: plain text. b := bytes.NewBuffer(data) _, err := fmt.Fscanln(b, &v.x, &v.y, &v.z)return err}// This example transmits a value that implements the custom encoding and decoding methods.func main() {var network bytes.Buffer // Stand-in for the network.// Create an encoder and send a value. enc := gob.NewEncoder(&network) err := enc.Encode(Vector{3, 4, 5})if err != nil { log.Fatal("encode:", err)}// Create a decoder and receive a value. dec := gob.NewDecoder(&network)var v Vector err = dec.Decode(&v)if err != nil { log.Fatal("decode:", err)} fmt.Println(v)}
此示例顯示如何對(duì)接口值進(jìn)行編碼。與常規(guī)類型的主要區(qū)別在于注冊(cè)實(shí)現(xiàn)接口的具體類型。
package mainimport ("bytes""encoding/gob""fmt""log""math")type Point struct { X, Y int}func (p Point) Hypotenuse() float64 {return math.Hypot(float64(p.X), float64(p.Y))}type Pythagoras interface {Hypotenuse() float64}// This example shows how to encode an interface value. The key// distinction from regular types is to register the concrete type that// implements the interface.func main() {var network bytes.Buffer // Stand-in for the network.// We must register the concrete type for the encoder and decoder (which would// normally be on a separate machine from the encoder). On each end, this tells the// engine which concrete type is being sent that implements the interface. gob.Register(Point{})// Create an encoder and send some values. enc := gob.NewEncoder(&network)for i := 1; i <= 3; i++ {interfaceEncode(enc, Point{3 * i, 4 * i})}// Create a decoder and receive some values. dec := gob.NewDecoder(&network)for i := 1; i <= 3; i++ { result := interfaceDecode(dec) fmt.Println(result.Hypotenuse())}}// interfaceEncode encodes the interface value into the encoder.func interfaceEncode(enc *gob.Encoder, p Pythagoras) {// The encode will fail unless the concrete type has been// registered. We registered it in the calling function.// Pass pointer to interface so Encode sees (and hence sends) a value of// interface type. If we passed p directly it would see the concrete type instead.// See the blog post, "The Laws of Reflection" for background. err := enc.Encode(&p)if err != nil { log.Fatal("encode:", err)}}// interfaceDecode decodes the next interface value from the stream and returns it.func interfaceDecode(dec *gob.Decoder) Pythagoras {// The decode will fail unless the concrete type on the wire has been// registered. We registered it in the calling function.var p Pythagoras err := dec.Decode(&p)if err != nil { log.Fatal("decode:", err)}return p}
func Register(value interface{})
func RegisterName(name string, value interface{})
type CommonType
type Decoder
func NewDecoder(r io.Reader) *Decoder
func (dec *Decoder) Decode(e interface{}) error
func (dec *Decoder) DecodeValue(v reflect.Value) error
type Encoder
func NewEncoder(w io.Writer) *Encoder
func (enc *Encoder) Encode(e interface{}) error
func (enc *Encoder) EncodeValue(value reflect.Value) error
type GobDecoder
type GobEncoder
Package (Basic) Package (EncodeDecode) Package (Interface)
dec_helpers.go decode.go decoder.go doc.go enc_helpers.go encode.go encoder.go error.go type.go
func Register(value interface{})
在其內(nèi)部類型名稱下注冊(cè)記錄類型,由該類型的值標(biāo)識(shí)。該名稱將標(biāo)識(shí)作為接口變量發(fā)送或接收的值的具體類型。只需要注冊(cè)將作為接口值實(shí)現(xiàn)傳輸?shù)念愋?。期望僅在初始化期間使用,如果類型和名稱之間的映射不是雙向映射,則會(huì)發(fā)生混亂。
func RegisterName(name string, value interface{})
RegisterName與Register類似,但使用提供的名稱而不是類型的默認(rèn)值。
CommonType保存所有類型的元素。它是一個(gè)歷史工件,保存為二進(jìn)制兼容性,并且僅為了包類型描述符的編碼而導(dǎo)出。它不適合客戶直接使用。
type CommonType struct { Name string Id typeId}
解碼器管理從連接的遠(yuǎn)程端讀取的類型和數(shù)據(jù)信息的接收。
解碼器只對(duì)解碼輸入大小進(jìn)行基本的理智檢查,并且其限制是不可配置的。解碼來(lái)自不受信任來(lái)源的gob數(shù)據(jù)時(shí)請(qǐng)小心。
type Decoder struct { // contains filtered or unexported fields}
func NewDecoder(r io.Reader) *Decoder
NewDecoder返回一個(gè)從io.Reader讀取的新解碼器。如果r不實(shí)現(xiàn)io.ByteReader,它將被包裝在一個(gè)bufio.Reader中。
func (dec *Decoder) Decode(e interface{}) error
解碼從輸入流中讀取下一個(gè)值并將其存儲(chǔ)在由空接口值表示的數(shù)據(jù)中。如果e為零,則該值將被丟棄。否則,e下面的值必須是指向下一個(gè)接收數(shù)據(jù)項(xiàng)的正確類型的指針。如果輸入是在EOF,解碼返回io.EOF并且不修改e。
func (dec *Decoder) DecodeValue(v reflect.Value) error
DecodeValue從輸入流中讀取下一個(gè)值。如果v是zero reflect.Value(v.Kind()==無(wú)效),則DecodeValue丟棄該值。否則,它將值存儲(chǔ)到v中。在這種情況下,v必須表示一個(gè)非零指向數(shù)據(jù)的指針,或者是可賦值的reflect.Value(v.CanSet())如果輸入位于EOF,DecodeValue返回io.EOF,不修改v。
編碼器管理類型和數(shù)據(jù)信息傳輸?shù)竭B接的另一端。
type Encoder struct { // contains filtered or unexported fields}
func NewEncoder(w io.Writer) *Encoder
NewEncoder返回一個(gè)將在io.Writer上傳輸?shù)男戮幋a器。
func (enc *Encoder) Encode(e interface{}) error
編碼傳輸由空接口值表示的數(shù)據(jù)項(xiàng),保證所有必需的類型信息先傳送。傳遞一個(gè)零指針給編碼器會(huì)驚慌,因?yàn)樗鼈儾荒芡ㄟ^(guò)gob傳輸。
func (enc *Encoder) EncodeValue(value reflect.Value) error
EncodeValue傳輸由反射值表示的數(shù)據(jù)項(xiàng),保證所有必要的類型信息都先傳輸完畢。將一個(gè)零指針傳遞給EncodeValue將會(huì)發(fā)生混亂,因?yàn)樗鼈儾荒芡ㄟ^(guò)gob進(jìn)行傳輸。
GobDecoder是描述數(shù)據(jù)的接口,它提供自己的例程來(lái)解碼由GobEncoder發(fā)送的傳輸值。
type GobDecoder interface { // GobDecode overwrites the receiver, which must be a pointer, // with the value represented by the byte slice, which was written // by GobEncode, usually for the same concrete type. GobDecode([]byte) error}
GobEncoder是描述數(shù)據(jù)的接口,它為編碼值提供了自己的表示,以便傳輸給GobDecoder。實(shí)現(xiàn)GobEncoder和GobDecoder的類型可以完全控制其數(shù)據(jù)的表示,因此可能包含私有字段,通道和函數(shù),這些通常不會(huì)在gob流中傳輸。
注意:由于gobs可以永久保存,因此確保GobEncoder使用的編碼在軟件變化時(shí)保持穩(wěn)定是一個(gè)很好的設(shè)計(jì)。例如,GobEncode在編碼中包含一個(gè)版本號(hào)可能是有意義的。
type GobEncoder interface { // GobEncode returns a byte slice representing the encoding of the // receiver for transmission to a GobDecoder, usually of the same // concrete type. GobEncode() ([]byte, error)}