On Friday, 12 March 2021 at 06:56:46 UTC axel.wa...@googlemail.com wrote:

> On Fri, Mar 12, 2021 at 3:26 AM Robert Engels <ren...@ix.netcom.com> 
> wrote:
>
>> I must be dense on this. I have no idea why there is any use of struct 
>> tags or JSON marshaling in the sample code.
>>
>
> To demonstrate why converting between different struct types is useful.
>
> If you want take an struct existing type (defined in a different package) 
> and change how it is marshalled (say, omit or rename a certain field) you'd 
> have to create a new struct type with different tags and copy over the 
> fields. This was deemed inconvenient 
> <https://github.com/golang/go/issues/6858>, so it was changed to the 
> current semantics in go 1.8 <https://golang.org/doc/go1.8#language>. OP 
> is pointing out that the change means adding a field to a struct is now a 
> backwards incompatible change, as someone might to this conversion.
>

I think I am also being dense.  I can see two separate things under 
discussion - compatibility of struct types for conversion, and 
backwards-compatibility of serialization [JSON? Protobuf?] - but I can't 
see what's being proposed to change.

I don't follow the argument that "adding a field to a struct is *now* a 
backwards incompatible change".  Surely this was always the case, 
regardless of tags?  That is, if you have

type T1 struct {
    Foo string
}

type T2 struct {
    Foo string
    Bar string
}

then what would you expect to happen for:

    v1 := T1{}
    v2 := T2(v1)   ??
...
    v2 := T2{}
    v1 := T1(v2)  ??

These two structures have different shapes.  In the first case, I suppose 
it could copy the matching members and create zero values for the new 
ones.  In the second case, I suppose it could copy the matching members and 
silently(!) discard the missing ones.  But either way, that just means the 
compiler magically writing code which copies member-by-member.  I'd rather 
do this by hand.

Even with magic conversions, trying to use a *t1 as a *t2 or vice versa 
would definitely not work, as they have differing layout in memory. Indeed, 
even the ordering of fields in memory must be the same for two structs to 
be compatible:
https://play.golang.org/p/BTUc6mNJQKS

However, if two structures have the same members in the same order, and 
differ only by tags, then they have the same shape.  Then it seems 
reasonable to me to treat a T1 as compatible with T2; copying can be done 
as a blob of bytes.  The change in 1.8 to omit comparing tags has made 
types more compatible, not less.

Separately from that, there's the issue of serialization and 
forwards/backwards compatibility.  I don't see any problem here.  For 
example, if you serialize a type T1 to JSON, and then deserialize to T2 
(which may have more or fewer fields), that all works fine.

https://play.golang.org/p/aJwObgyRhan

If you want to reject unexpected fields when deserializing, there are 
options for doing that.  But by default, they are compatible in both 
directions.  You can also re-order the fields in the struct, since the JSON 
deserialization is assigning elements individually.

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/36e1a048-2505-4841-8882-a9b16a33fd57n%40googlegroups.com.

Reply via email to