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

This feels like saying, if a customer implements an interface and that
interface adds a method, it is up to the user to decide how to handle it.

There is even a suggestion to use private method like how you suggested
using private fields. The only difference is adding methods to all public
interfaces IS defined as a breaking and generally anticanon.

On Fri, 12 Mar 2021, 09:35 Brian Candler, <b.cand...@pobox.com> wrote:

> 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://urldefense.proofpoint.com/v2/url?u=https-3A__golang.org_doc_go1.8-23language&d=DwMFaQ&c=ncDTmphkJTvjIDPh0hpF_w&r=OaiRsMTFeJ0tMmMJQ5CwMuxNMvWoKXAJr-ebE3c5HU8&m=ymdbzPHlqzAZKoexWVIiBZtzqcg1g-TeYfTzKTHHkHU&s=RtGntkDdl9C6XLqF_LM45AUHEnrTTziLgrYa2fc8fdw&e=>.
>>> 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
>> <https://urldefense.proofpoint.com/v2/url?u=https-3A__play.golang.org_p_BTUc6mNJQKS&d=DwMFaQ&c=ncDTmphkJTvjIDPh0hpF_w&r=OaiRsMTFeJ0tMmMJQ5CwMuxNMvWoKXAJr-ebE3c5HU8&m=ymdbzPHlqzAZKoexWVIiBZtzqcg1g-TeYfTzKTHHkHU&s=6ov1ae-sS1KtoTu_dMdvwIRmKHwAbHvUvkoKvCWxK3U&e=>
>>
>> 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
>> <https://urldefense.proofpoint.com/v2/url?u=https-3A__play.golang.org_p_aJwObgyRhan&d=DwMFaQ&c=ncDTmphkJTvjIDPh0hpF_w&r=OaiRsMTFeJ0tMmMJQ5CwMuxNMvWoKXAJr-ebE3c5HU8&m=ymdbzPHlqzAZKoexWVIiBZtzqcg1g-TeYfTzKTHHkHU&s=t3P3cSzA1eKzO-XyW7zdxgt5vvFTQUEezS1UY9a8atQ&e=>
>>
>> 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 a topic in the
> Google Groups "golang-nuts" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/golang-nuts/oAjxpH-Qq2Y/unsubscribe.
> To unsubscribe from this group and all its topics, 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
> <https://groups.google.com/d/msgid/golang-nuts/d091ff96-0407-4e82-b098-ffd4b37f6377n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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/CADJfOyV8%3DByiUbgw3y%2BLp0Xtn7M%3DusmRhpsYv2sUVjn_vq6%2Bag%40mail.gmail.com.

Reply via email to