> 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.