I don’t think you can separate the two - it seems the OP purpose of using the 
struct conversion is to facilitate a different serialization format. This is a 
place where Gos convenience (struct tags) is running into explicitness. The 
struct conversion is nothing more than a magic copy. Make this a method in 
reflect with parameters and call it a day. 

> On Mar 12, 2021, at 6:15 AM, 'Axel Wagner' via golang-nuts 
> <golang-nuts@googlegroups.com> wrote:
> 
> 
>> On Fri, Mar 12, 2021 at 10:16 AM Brian Candler <b.cand...@pobox.com> wrote:
> 
>> I can see two separate things under discussion - compatibility of struct 
>> types for conversion, and backwards-compatibility of serialization [JSON? 
>> Protobuf?]
> 
> Backwards-compatibility of serialization is a red herring. It is off-topic as 
> far as this thread is concerned, this is purely about language-level 
> compatibility of types.
>  
>> but I can't see what's being proposed to change.
> 
> I think the proposed change can be summarized as roughly
> 
>> Either
>> 1. Create consensus that adding an (exported) field to a struct should be 
>> considered a backwards incompatible change, or
>> 2. Create consensus that converting one struct type into a different struct 
>> type should be considered deprecated, as it makes you vulnerable to getting 
>> broken by someone adding a field.
>> Take either consensus and put it into the Go 1 compatibility promise and 
>> potentially encode it into a vet check.
> 
> That is my understanding of what's "proposed". Personally, as I said, I'm not 
> in favor of either. I think both statements lack nuance.
> 
> The logical conclusions of the arguments brought forth is that every publicly 
> visible change is a breaking change. So if we follow that logic we'd end up 
> (in my opinion) in an ecosystem where every module is constantly incrementing 
> their major versions because "we technically broke the API". I think that is 
> undesirable.
> 
> Given that every publicly visible change to an exported identifier can be 
> considered a breaking change, I personally don't think it's all that useful 
> to talk about interface-changes vs. struct changes and which of them are 
> breaking. Both are - in some circumstances. And in some circumstance, neither 
> are. It's more useful to talk about *how frequently* any given change leads 
> to breakages. I think it's easy to make an argument that changing in 
> interface type will lead to very frequent breakages - it will either break 
> every implementation of the interface, or any usage of the interface, or both.
> 
> Meanwhile, I think it's also not that hard to make an argument that breakages 
> causing by converting one struct type into another and then adding a field to 
> one of them are comparatively rare. And even within that, there is nuance, 
> where it is more frequent for some kind of types (POD - plain-old-data) than 
> others (e.g. http.Server or other types used to abstract and bundle state).
> 
> That's why I don't think a vet check would work. It can't distinguish the 
> case of a struct being POD vs. the struct bundling state. And I would even 
> argue that generally, the "bundling state" case is more common in Go.
> 
>> 
>> 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.
> 
> -- 
> 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/CAEkBMfE09%2BW0MU55LeJfm-9BNM_7SZhGkfRxD4wkP4Rj53Eq_A%40mail.gmail.com.

-- 
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/7F8DA101-0694-4CD3-9E2E-F5F9F6330B13%40ix.netcom.com.

Reply via email to