FAQ
I am trying to understand how gob encodes interfaces but there are certain
values produced by the library that don't seem to be internally consistent.

I define a few structs with interface members:

type t1 struct{}
type t2 struct{ I interface{} }
type t3 struct{ J interface{} }

and then Encode a value that nests these structs: t3{t2{t1{}}}

http://play.golang.org/p/5dIPn7Xfg3

Based on documentation, I am interpreting the output as follows:

  1 0x16 - message of length 22
  2 0xff - new typeId
  3 0x81
  4 0x3 - wireType 3rd field (structType)
  5 0x1 - structType 1st field (CommonType)
  6 0x1 - CommonType 1st field (name)
  7 0x2 - string length 2
  8 0x74 - 't'
  9 0x33 - '3'
10 0x1 - CommonType 2nd field (typeId)
11 0xff
12 0x82
13 0x0 - end CommonType
14 0x1 - structType 2nd field ([]*fieldType)
15 0x1 - slice length 1
16 0x1 - fieldType 1st field (name)
17 0x1 - string length 1
18 0x4a - 'J'
19 0x1 - fieldType 2nd field (typeId)
20 0x10 - interface
21 0x0 - end fieldType
22 0x0 - end structType
23 0x0 - end wireType
         -- end of message started at byte 1 --

*24 0x22 - message of length 34*
25 0xff - existing typeId (t3)
26 0x82
27 0x1 - t3 1st field (J interface{})
28 0x8 - string length 8
29 0x2a - '*'
30 0x6d - 'm'
31 0x61 - 'a'
32 0x69 - 'i'
33 0x6e - 'n'
34 0x2e - '.'
35 0x74 - 't'
36 0x32 - '2'
37 0xff - new typeId
38 0x83
39 0x3 - wireType 3rd field (structType)
40 0x1 - structType 1st field (CommonType)
41 0x1 - CommonType 1st field (name)
42 0x2 - string length 2
43 0x74 - 't'
44 0x32 - '2'
45 0x1 - CommonType 2nd field (typeId)
46 0xff
47 0x84
48 0x0 - end CommonType
49 0x1 - structType 2nd field ([]*fieldType)
50 0x1 - slice length 1
51 0x1 - fieldType 1st field (name)
52 0x1 - string length 1
53 0x49 - 'I'
54 0x1 - fieldType 2nd field (typeId)
55 0x10 - interface
56 0x0 - end fieldType
57 0x0 - end structType
58 0x0 - end wireType
* -- end of message started at byte 24 --*

*59 0x22 - message of length 34*
60 0xff - existing typeId (t2)
61 0x84
*62 0x18 - message of length 24 (WHY?)*
63 0x1 - t2 1st field (I interface{})
64 0x8 - string length 8
65 0x2a - '*'
66 0x6d - 'm'
67 0x61 - 'a'
68 0x69 - 'i'
69 0x6e - 'n'
70 0x2e - '.'
71 0x74 - 't'
72 0x31 - '1'
73 0xff - new typeId
74 0x85
75 0x3 - wireType 3rd field (structType)
76 0x1 - structType 1st field (CommonType)
77 0x1 - CommonType 1st field (name)
78 0x2 - string length 2
79 0x74 - 't'
80 0x31 - '1'
81 0x1 - CommonType 2nd field (typeId)
82 0xff
83 0x86
84 0x0 - end CommonType
85 0x0 - end structType (no fields)
86 0x0 - end wireType
* -- end of message started at byte 62 --*
*87 0x5 - message of length 5*
88 0xff - existing typeId (t1)
89 0x86
90 0x1 - t1 1st field ?
91 0x0 - end t1
92 0x0 - end t2
* -- end of message started at byte 87 --*
93 0x0 - end t3
* -- end of message started at byte 59 --*

I have two questions about "messages" (defined by the message lengths
included in the stream).

Firstly, when encoding t3 (starting at byte 24), gob advances to the first
field (an interface), writes the name of the underlying type stored in that
field, then defines the underlying stored type. However when encoding t2
(starting at byte 59), gob *starts a new message* (byte 62), advances to
the first field (an interface), writes the name of the underlying type
stored in that field, then defines the underlying stored type. Why the new
message at byte 62? And why not a similar message start after byte 26?

Secondly, how are messages broken up? It seems gob starts encoding the
outermost value (t3{...}) at byte 24 and doesn't finish until byte 93.
Shouldn't the length encoded at byte 24 be 69 bytes instead of 34? If the
purpose of the message lengths is to skip values, then skipping 34 bytes
starting at byte 24 would land the reader at the beginning of a t2 struct
which shouldn't exist if the enclosing t3 has been properly skipped.

Lastly, why is t1 encoded starting at byte 87? t1 is an empty struct so all
values of it are its zero value and should never be encoded. And what is
byte 90? There is no first field to advance to.

It may just be me misreading the docs, but I feel the data on the wire
differs structurally from the docs.

Advice/pointers appreciated,

-v

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Roberto Zanotto at Oct 25, 2015 at 3:07 pm
    I'm also interested in the topic.
    I suspect that a new message is created for each call to Encode. In
    particular, the fields of a struct are encoded "recursively", which is why
    a new message is created for each field (if I understand correctly).
    On Saturday, October 24, 2015 at 8:28:05 PM UTC+2, Vivek Sekhar wrote:

    I am trying to understand how gob encodes interfaces but there are certain
    values produced by the library that don't seem to be internally consistent.

    I define a few structs with interface members:

    type t1 struct{}
    type t2 struct{ I interface{} }
    type t3 struct{ J interface{} }

    and then Encode a value that nests these structs: t3{t2{t1{}}}

    http://play.golang.org/p/5dIPn7Xfg3

    Based on documentation, I am interpreting the output as follows:

    1 0x16 - message of length 22
    2 0xff - new typeId
    3 0x81
    4 0x3 - wireType 3rd field (structType)
    5 0x1 - structType 1st field (CommonType)
    6 0x1 - CommonType 1st field (name)
    7 0x2 - string length 2
    8 0x74 - 't'
    9 0x33 - '3'
    10 0x1 - CommonType 2nd field (typeId)
    11 0xff
    12 0x82
    13 0x0 - end CommonType
    14 0x1 - structType 2nd field ([]*fieldType)
    15 0x1 - slice length 1
    16 0x1 - fieldType 1st field (name)
    17 0x1 - string length 1
    18 0x4a - 'J'
    19 0x1 - fieldType 2nd field (typeId)
    20 0x10 - interface
    21 0x0 - end fieldType
    22 0x0 - end structType
    23 0x0 - end wireType
    -- end of message started at byte 1 --

    *24 0x22 - message of length 34*
    25 0xff - existing typeId (t3)
    26 0x82
    27 0x1 - t3 1st field (J interface{})
    28 0x8 - string length 8
    29 0x2a - '*'
    30 0x6d - 'm'
    31 0x61 - 'a'
    32 0x69 - 'i'
    33 0x6e - 'n'
    34 0x2e - '.'
    35 0x74 - 't'
    36 0x32 - '2'
    37 0xff - new typeId
    38 0x83
    39 0x3 - wireType 3rd field (structType)
    40 0x1 - structType 1st field (CommonType)
    41 0x1 - CommonType 1st field (name)
    42 0x2 - string length 2
    43 0x74 - 't'
    44 0x32 - '2'
    45 0x1 - CommonType 2nd field (typeId)
    46 0xff
    47 0x84
    48 0x0 - end CommonType
    49 0x1 - structType 2nd field ([]*fieldType)
    50 0x1 - slice length 1
    51 0x1 - fieldType 1st field (name)
    52 0x1 - string length 1
    53 0x49 - 'I'
    54 0x1 - fieldType 2nd field (typeId)
    55 0x10 - interface
    56 0x0 - end fieldType
    57 0x0 - end structType
    58 0x0 - end wireType
    * -- end of message started at byte 24 --*

    *59 0x22 - message of length 34*
    60 0xff - existing typeId (t2)
    61 0x84
    *62 0x18 - message of length 24 (WHY?)*
    63 0x1 - t2 1st field (I interface{})
    64 0x8 - string length 8
    65 0x2a - '*'
    66 0x6d - 'm'
    67 0x61 - 'a'
    68 0x69 - 'i'
    69 0x6e - 'n'
    70 0x2e - '.'
    71 0x74 - 't'
    72 0x31 - '1'
    73 0xff - new typeId
    74 0x85
    75 0x3 - wireType 3rd field (structType)
    76 0x1 - structType 1st field (CommonType)
    77 0x1 - CommonType 1st field (name)
    78 0x2 - string length 2
    79 0x74 - 't'
    80 0x31 - '1'
    81 0x1 - CommonType 2nd field (typeId)
    82 0xff
    83 0x86
    84 0x0 - end CommonType
    85 0x0 - end structType (no fields)
    86 0x0 - end wireType
    * -- end of message started at byte 62 --*
    *87 0x5 - message of length 5*
    88 0xff - existing typeId (t1)
    89 0x86
    90 0x1 - t1 1st field ?
    91 0x0 - end t1
    92 0x0 - end t2
    * -- end of message started at byte 87 --*
    93 0x0 - end t3
    * -- end of message started at byte 59 --*

    I have two questions about "messages" (defined by the message lengths
    included in the stream).

    Firstly, when encoding t3 (starting at byte 24), gob advances to the first
    field (an interface), writes the name of the underlying type stored in that
    field, then defines the underlying stored type. However when encoding t2
    (starting at byte 59), gob *starts a new message* (byte 62), advances to
    the first field (an interface), writes the name of the underlying type
    stored in that field, then defines the underlying stored type. Why the new
    message at byte 62? And why not a similar message start after byte 26?

    Secondly, how are messages broken up? It seems gob starts encoding the
    outermost value (t3{...}) at byte 24 and doesn't finish until byte 93.
    Shouldn't the length encoded at byte 24 be 69 bytes instead of 34? If the
    purpose of the message lengths is to skip values, then skipping 34 bytes
    starting at byte 24 would land the reader at the beginning of a t2 struct
    which shouldn't exist if the enclosing t3 has been properly skipped.

    Lastly, why is t1 encoded starting at byte 87? t1 is an empty struct so
    all values of it are its zero value and should never be encoded. And what
    is byte 90? There is no first field to advance to.

    It may just be me misreading the docs, but I feel the data on the wire
    differs structurally from the docs.

    Advice/pointers appreciated,

    -v
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedOct 24, '15 at 6:27p
activeOct 25, '15 at 3:07p
posts2
users2
websitegolang.org

2 users in discussion

Roberto Zanotto: 1 post Vivek Sekhar: 1 post

People

Translate

site design / logo © 2021 Grokbase