| // 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 |
| } |