On Friday, 12 March 2021 at 06:56:46 UTC [email protected] wrote:
> On Fri, Mar 12, 2021 at 3:26 AM Robert Engels <[email protected]>
> 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/36e1a048-2505-4841-8882-a9b16a33fd57n%40googlegroups.com.