Maybe the argument goes something like this:

* package P exports a struct type T1
* package Q deals with values of type T1
* package Q wants to serialize objects of type T1, but T1 doesn't have the 
desired set of tags; so it defines a new type T2 which is the same as T1 
but with different tags
* it uses v2 := T2(v1) and then proceeds to serialize it
* if package P changes the type T1, then this breaks package Q

If that's the problem statement, then I'd say:

1. if T1 has any private fields, it's impossible to make a T2 which is 
compatible with it anyway (AFAICS).
https://play.golang.org/p/5QND-BdsMuR

2. if T1 changes to add a new public field, then the consumer *must* make a 
decision as to what to do about this extra field.  Should it exclude it 
from the JSON representation, or include it, or include it as 'optional' 
(i.e. present if non-zero)?  What JSON key should it use?  Often you don't 
want the default capitalization of the name.

Hence breakage seems entirely reasonable to me, to force the user of T1 to 
decide how to handle it.

On Friday, 12 March 2021 at 09:15:45 UTC Brian Candler wrote:

> 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/d091ff96-0407-4e82-b098-ffd4b37f6377n%40googlegroups.com.

Reply via email to