github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/doc/articles/gobs_of_data.html (about)

     1  <!--{
     2  "Title": "Gobs of data",
     3  "Template": true
     4  }-->
     5  
     6  <p>
     7  To transmit a data structure across a network or to store it in a file, it must
     8  be encoded and then decoded again. There are many encodings available, of
     9  course: <a href="http://www.json.org/">JSON</a>,
    10  <a href="http://www.w3.org/XML/">XML</a>, Google's
    11  <a href="http://code.google.com/p/protobuf">protocol buffers</a>, and more.
    12  And now there's another, provided by Go's <a href="/pkg/encoding/gob/">gob</a>
    13  package.
    14  </p>
    15  
    16  <p>
    17  Why define a new encoding? It's a lot of work and redundant at that. Why not
    18  just use one of the existing formats? Well, for one thing, we do! Go has
    19  <a href="/pkg/">packages</a> supporting all the encodings just mentioned (the
    20  <a href="http://code.google.com/p/goprotobuf">protocol buffer package</a> is in
    21  a separate repository but it's one of the most frequently downloaded). And for
    22  many purposes, including communicating with tools and systems written in other
    23  languages, they're the right choice.
    24  </p>
    25  
    26  <p>
    27  But for a Go-specific environment, such as communicating between two servers
    28  written in Go, there's an opportunity to build something much easier to use and
    29  possibly more efficient.
    30  </p>
    31  
    32  <p>
    33  Gobs work with the language in a way that an externally-defined,
    34  language-independent encoding cannot. At the same time, there are lessons to be
    35  learned from the existing systems.
    36  </p>
    37  
    38  <p>
    39  <b>Goals</b>
    40  </p>
    41  
    42  <p>
    43  The gob package was designed with a number of goals in mind.
    44  </p>
    45  
    46  <p>
    47  First, and most obvious, it had to be very easy to use. First, because Go has
    48  reflection, there is no need for a separate interface definition language or
    49  "protocol compiler". The data structure itself is all the package should need
    50  to figure out how to encode and decode it. On the other hand, this approach
    51  means that gobs will never work as well with other languages, but that's OK:
    52  gobs are unashamedly Go-centric.
    53  </p>
    54  
    55  <p>
    56  Efficiency is also important. Textual representations, exemplified by XML and
    57  JSON, are too slow to put at the center of an efficient communications network.
    58  A binary encoding is necessary.
    59  </p>
    60  
    61  <p>
    62  Gob streams must be self-describing. Each gob stream, read from the beginning,
    63  contains sufficient information that the entire stream can be parsed by an
    64  agent that knows nothing a priori about its contents. This property means that
    65  you will always be able to decode a gob stream stored in a file, even long
    66  after you've forgotten what data it represents.
    67  </p>
    68  
    69  <p>
    70  There were also some things to learn from our experiences with Google protocol
    71  buffers.
    72  </p>
    73  
    74  <p>
    75  <b>Protocol buffer misfeatures</b>
    76  </p>
    77  
    78  <p>
    79  Protocol buffers had a major effect on the design of gobs, but have three
    80  features that were deliberately avoided. (Leaving aside the property that
    81  protocol buffers aren't self-describing: if you don't know the data definition
    82  used to encode a protocol buffer, you might not be able to parse it.)
    83  </p>
    84  
    85  <p>
    86  First, protocol buffers only work on the data type we call a struct in Go. You
    87  can't encode an integer or array at the top level, only a struct with fields
    88  inside it. That seems a pointless restriction, at least in Go. If all you want
    89  to send is an array of integers, why should you have to put it into a
    90  struct first?
    91  </p>
    92  
    93  <p>
    94  Next, a protocol buffer definition may specify that fields <code>T.x</code> and
    95  <code>T.y</code> are required to be present whenever a value of type
    96  <code>T</code> is encoded or decoded.  Although such required fields may seem
    97  like a good idea, they are costly to implement because the codec must maintain a
    98  separate data structure while encoding and decoding, to be able to report when
    99  required fields are missing.  They're also a maintenance problem. Over time, one
   100  may want to modify the data definition to remove a required field, but that may
   101  cause existing clients of the data to crash. It's better not to have them in the
   102  encoding at all.  (Protocol buffers also have optional fields. But if we don't
   103  have required fields, all fields are optional and that's that. There will be
   104  more to say about optional fields a little later.)
   105  </p>
   106  
   107  <p>
   108  The third protocol buffer misfeature is default values. If a protocol buffer
   109  omits the value for a "defaulted" field, then the decoded structure behaves as
   110  if the field were set to that value. This idea works nicely when you have
   111  getter and setter methods to control access to the field, but is harder to
   112  handle cleanly when the container is just a plain idiomatic struct. Required
   113  fields are also tricky to implement: where does one define the default values,
   114  what types do they have (is text UTF-8? uninterpreted bytes? how many bits in a
   115  float?) and despite the apparent simplicity, there were a number of
   116  complications in their design and implementation for protocol buffers. We
   117  decided to leave them out of gobs and fall back to Go's trivial but effective
   118  defaulting rule: unless you set something otherwise, it has the "zero value"
   119  for that type - and it doesn't need to be transmitted.
   120  </p>
   121  
   122  <p>
   123  So gobs end up looking like a sort of generalized, simplified protocol buffer.
   124  How do they work?
   125  </p>
   126  
   127  <p>
   128  <b>Values</b>
   129  </p>
   130  
   131  <p>
   132  The encoded gob data isn't about <code>int8</code>s and <code>uint16</code>s.
   133  Instead, somewhat analogous to constants in Go, its integer values are abstract,
   134  sizeless numbers, either signed or unsigned. When you encode an
   135  <code>int8</code>, its value is transmitted as an unsized, variable-length
   136  integer. When you encode an <code>int64</code>, its value is also transmitted as
   137  an unsized, variable-length integer. (Signed and unsigned are treated
   138  distinctly, but the same unsized-ness applies to unsigned values too.) If both
   139  have the value 7, the bits sent on the wire will be identical. When the receiver
   140  decodes that value, it puts it into the receiver's variable, which may be of
   141  arbitrary integer type. Thus an encoder may send a 7 that came from an
   142  <code>int8</code>, but the receiver may store it in an <code>int64</code>. This
   143  is fine: the value is an integer and as a long as it fits, everything works. (If
   144  it doesn't fit, an error results.) This decoupling from the size of the variable
   145  gives some flexibility to the encoding: we can expand the type of the integer
   146  variable as the software evolves, but still be able to decode old data.
   147  </p>
   148  
   149  <p>
   150  This flexibility also applies to pointers. Before transmission, all pointers are
   151  flattened. Values of type <code>int8</code>, <code>*int8</code>,
   152  <code>**int8</code>, <code>****int8</code>, etc. are all transmitted as an
   153  integer value, which may then be stored in <code>int</code> of any size, or
   154  <code>*int</code>, or <code>******int</code>, etc. Again, this allows for
   155  flexibility.
   156  </p>
   157  
   158  <p>
   159  Flexibility also happens because, when decoding a struct, only those fields
   160  that are sent by the encoder are stored in the destination. Given the value
   161  </p>
   162  
   163  {{code "/doc/progs/gobs1.go" `/type T/` `/STOP/`}}
   164  
   165  <p>
   166  the encoding of <code>t</code> sends only the 7 and 8. Because it's zero, the
   167  value of <code>Y</code> isn't even sent; there's no need to send a zero value.
   168  </p>
   169  
   170  <p>
   171  The receiver could instead decode the value into this structure:
   172  </p>
   173  
   174  {{code "/doc/progs/gobs1.go" `/type U/` `/STOP/`}}
   175  
   176  <p>
   177  and acquire a value of <code>u</code> with only <code>X</code> set (to the
   178  address of an <code>int8</code> variable set to 7); the <code>Z</code> field is
   179  ignored - where would you put it? When decoding structs, fields are matched by
   180  name and compatible type, and only fields that exist in both are affected. This
   181  simple approach finesses the "optional field" problem: as the type
   182  <code>T</code> evolves by adding fields, out of date receivers will still
   183  function with the part of the type they recognize. Thus gobs provide the
   184  important result of optional fields - extensibility - without any additional
   185  mechanism or notation.
   186  </p>
   187  
   188  <p>
   189  From integers we can build all the other types: bytes, strings, arrays, slices,
   190  maps, even floats. Floating-point values are represented by their IEEE 754
   191  floating-point bit pattern, stored as an integer, which works fine as long as
   192  you know their type, which we always do. By the way, that integer is sent in
   193  byte-reversed order because common values of floating-point numbers, such as
   194  small integers, have a lot of zeros at the low end that we can avoid
   195  transmitting.
   196  </p>
   197  
   198  <p>
   199  One nice feature of gobs that Go makes possible is that they allow you to define
   200  your own encoding by having your type satisfy the
   201  <a href="/pkg/encoding/gob/#GobEncoder">GobEncoder</a> and
   202  <a href="/pkg/encoding/gob/#GobDecoder">GobDecoder</a> interfaces, in a manner
   203  analogous to the <a href="/pkg/encoding/json/">JSON</a> package's
   204  <a href="/pkg/encoding/json/#Marshaler">Marshaler</a> and
   205  <a href="/pkg/encoding/json/#Unmarshaler">Unmarshaler</a> and also to the
   206  <a href="/pkg/fmt/#Stringer">Stringer</a> interface from
   207  <a href="/pkg/fmt/">package fmt</a>. This facility makes it possible to
   208  represent special features, enforce constraints, or hide secrets when you
   209  transmit data. See the <a href="/pkg/encoding/gob/">documentation</a> for
   210  details.
   211  </p>
   212  
   213  <p>
   214  <b>Types on the wire</b>
   215  </p>
   216  
   217  <p>
   218  The first time you send a given type, the gob package includes in the data
   219  stream a description of that type. In fact, what happens is that the encoder is
   220  used to encode, in the standard gob encoding format, an internal struct that
   221  describes the type and gives it a unique number. (Basic types, plus the layout
   222  of the type description structure, are predefined by the software for
   223  bootstrapping.) After the type is described, it can be referenced by its type
   224  number.
   225  </p>
   226  
   227  <p>
   228  Thus when we send our first type <code>T</code>, the gob encoder sends a
   229  description of <code>T</code> and tags it with a type number, say 127. All
   230  values, including the first, are then prefixed by that number, so a stream of
   231  <code>T</code> values looks like:
   232  </p>
   233  
   234  <pre>
   235  ("define type id" 127, definition of type T)(127, T value)(127, T value), ...
   236  </pre>
   237  
   238  <p>
   239  These type numbers make it possible to describe recursive types and send values
   240  of those types. Thus gobs can encode types such as trees:
   241  </p>
   242  
   243  {{code "/doc/progs/gobs1.go" `/type Node/` `/STOP/`}}
   244  
   245  <p>
   246  (It's an exercise for the reader to discover how the zero-defaulting rule makes
   247  this work, even though gobs don't represent pointers.)
   248  </p>
   249  
   250  <p>
   251  With the type information, a gob stream is fully self-describing except for the
   252  set of bootstrap types, which is a well-defined starting point.
   253  </p>
   254  
   255  <p>
   256  <b>Compiling a machine</b>
   257  </p>
   258  
   259  <p>
   260  The first time you encode a value of a given type, the gob package builds a
   261  little interpreted machine specific to that data type. It uses reflection on
   262  the type to construct that machine, but once the machine is built it does not
   263  depend on reflection. The machine uses package unsafe and some trickery to
   264  convert the data into the encoded bytes at high speed. It could use reflection
   265  and avoid unsafe, but would be significantly slower. (A similar high-speed
   266  approach is taken by the protocol buffer support for Go, whose design was
   267  influenced by the implementation of gobs.) Subsequent values of the same type
   268  use the already-compiled machine, so they can be encoded right away.
   269  </p>
   270  
   271  <p>
   272  Decoding is similar but harder. When you decode a value, the gob package holds
   273  a byte slice representing a value of a given encoder-defined type to decode,
   274  plus a Go value into which to decode it. The gob package builds a machine for
   275  that pair: the gob type sent on the wire crossed with the Go type provided for
   276  decoding. Once that decoding machine is built, though, it's again a
   277  reflectionless engine that uses unsafe methods to get maximum speed.
   278  </p>
   279  
   280  <p>
   281  <b>Use</b>
   282  </p>
   283  
   284  <p>
   285  There's a lot going on under the hood, but the result is an efficient,
   286  easy-to-use encoding system for transmitting data. Here's a complete example
   287  showing differing encoded and decoded types. Note how easy it is to send and
   288  receive values; all you need to do is present values and variables to the
   289  <a href="/pkg/encoding/gob/">gob package</a> and it does all the work.
   290  </p>
   291  
   292  {{code "/doc/progs/gobs2.go" `/package main/` `$`}}
   293  
   294  <p>
   295  You can compile and run this example code in the
   296  <a href="http://play.golang.org/p/_-OJV-rwMq">Go Playground</a>.
   297  </p>
   298  
   299  <p>
   300  The <a href="/pkg/net/rpc/">rpc package</a> builds on gobs to turn this
   301  encode/decode automation into transport for method calls across the network.
   302  That's a subject for another article.
   303  </p>
   304  
   305  <p>
   306  <b>Details</b>
   307  </p>
   308  
   309  <p>
   310  The <a href="/pkg/encoding/gob/">gob package documentation</a>, especially the
   311  file <a href="/src/pkg/encoding/gob/doc.go">doc.go</a>, expands on many of the
   312  details described here and includes a full worked example showing how the
   313  encoding represents data. If you are interested in the innards of the gob
   314  implementation, that's a good place to start.
   315  </p>