|  | // Copyright 2013 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package gob_test | 
|  |  | 
|  | import ( | 
|  | "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 Example_interface() { | 
|  | 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()) | 
|  | } | 
|  |  | 
|  | // Output: | 
|  | // 5 | 
|  | // 10 | 
|  | // 15 | 
|  | } | 
|  |  | 
|  | // 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 | 
|  | } |