[
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)