[ https://issues.apache.org/jira/browse/THRIFT-2189?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14295904#comment-14295904 ]
Johannes Martinsson commented on THRIFT-2189: --------------------------------------------- I understand that the wire format does not require the flag. The issue is that the Go code does *not* know which field is set, or at least it doesn't bother to check. Because of this when writing a union you can get a runtime panic. Here follows a simple example with a Thrift definition and small go program that causes a runtime panic. {code} namespace go poc struct X { 1: required byte a } struct Y { 1: required byte a } union Z { 1: X x 2: Y y } {code} And the Go program using the generated code, here placed in a package called "poc". {code} package main import ( "bytes" "fmt" "poc" "git.apache.org/thrift.git/lib/go/thrift" ) func main() { z := poc.Z{ X: &poc.X{A: int8(1)}, } var b []byte buffer := bytes.NewBuffer(b) trans := thrift.NewStreamTransportW(buffer) proto := thrift.NewTBinaryProtocolTransport(trans) z.Write(proto) trans.Flush() fmt.Printf("Written: %#v\n", buffer.Bytes()) } {code} Compiling and running this program generates the following output: {code} panic: runtime error: invalid memory address or nil pointer dereference [signal 0xb code=0x1 addr=0x0 pc=0x45a718] goroutine 1 [running]: poc.(*Y).writeField1(0x0, 0x7f7572620f68, 0xc20805e090, 0x0, 0x0) /home/majoh/tmp/thrift-union-poc/src/poc/ttypes.go:195 +0x1b8 poc.(*Y).Write(0x0, 0x7f7572620f68, 0xc20805e090, 0x0, 0x0) /home/majoh/tmp/thrift-union-poc/src/poc/ttypes.go:179 +0x1d5 poc.(*Z).writeField2(0xc20800a830, 0x7f7572620f68, 0xc20805e090, 0x0, 0x0) /home/majoh/tmp/thrift-union-poc/src/poc/ttypes.go:334 +0x1df poc.(*Z).Write(0xc20800a830, 0x7f7572620f68, 0xc20805e090, 0x0, 0x0) /home/majoh/tmp/thrift-union-poc/src/poc/ttypes.go:305 +0x238 main.main() /home/majoh/tmp/thrift-union-poc/poc.go:23 +0x202 exit status 2 {code} If the thrift definition is altered as to remove the second field of the union, the program generates the following output: {code} Written: []byte{0xc, 0x0, 0x1, 0x3, 0x0, 0x1, 0x1, 0x0, 0x0} {code} If instead we keep the original thrift definitions and instead set both fields of {{z}}, the program generates the following output: {code} Written: []byte{0xc, 0x0, 0x1, 0x3, 0x0, 0x1, 0x1, 0x0, 0xc, 0x0, 0x2, 0x3, 0x0, 0x1, 0x1, 0x0, 0x0} {code} (I.e. it is writing both fields, unless I missunderstand how the wire protocol works.) The relevant bit of the generated Go code I believe is the following, which unconditionally tries to write *all* fields of the union: {code} func (p *Z) Write(oprot thrift.TProtocol) error { if err := oprot.WriteStructBegin("Z"); err != nil { return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) } if err := p.writeField1(oprot); err != nil { return err } if err := p.writeField2(oprot); err != nil { return err } if err := oprot.WriteFieldStop(); err != nil { return thrift.PrependError("write field stop error: ", err) } if err := oprot.WriteStructEnd(); err != nil { return thrift.PrependError("write struct stop error: ", err) } return nil } {code} > Go does not support "union" type > -------------------------------- > > Key: THRIFT-2189 > URL: https://issues.apache.org/jira/browse/THRIFT-2189 > Project: Thrift > Issue Type: Bug > Components: Go - Compiler > Reporter: Jack L > Assignee: Jens Geyer > Fix For: 1.0 > > > Go thrift compiler does not support union types -- This message was sent by Atlassian JIRA (v6.3.4#6332)