2019-08-04 05:10
浏览 377


I'm trying to send a proto3 struct to a gRPC server with Go. The struct has an oneof type, which I seem to populate fine. When sending the message to my gRPC client, I get a panic about invalid memory address or nil pointer reference.

I have the proto definition (full file is at

# proto3

message Document {
  string collection = 1;
  string id = 2;
  oneof geo {
    Point point = 4;
    LineString line = 5;
    Bounds bounds = 6;
    string geojson = 7;

message Point { Coordinate coord = 1; }

message Coordinate {
  double lat = 1;
  double lng = 2;

The Go code is:

// create a coordinate
coord := geofancy.Coordinate{
  Lat: 10.2,
  Lng: -15.3,
// add coordinate to a point
point := geofancy.Point{
  Coord: &coord,

// these statements print valid data
log.Printf("Coord: %v", coord)
log.Printf("Point: %v", point)

// create document, add point to the oneof field
document := geofancy.Document{
  Collection:   "some-collection",
  Id:           "some-id",
  Geo:          &point,

// this prints the document correctly
log.Printf("Document: %v", document)

// connect to client
var opts []grpc.DialOption
opts = append(opts, grpc.WithInsecure())
var err error
conn, err := grpc.Dial("my-server:port", opts...)
if err != nil {
    log.Fatalf("fail to dial: %v", err)
defer conn.Close()
client := geofancy.NewGeofancyServiceClient(conn)

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

// this panics each time
res, err := client.SetDocument(ctx, &document)

The stack trace looks like:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x10 pc=0x54d731]

goroutine 1 [running]:
my-project/vendor/, 0x0, 0x0)
        D:/projects/golang/src/my-project/vendor/ +0x131
my-project/vendor/*marshalInfo).size(0xc0003021c0, 0xc000068cc0, 0xf9ef40)
        D:/projects/golang/src/my-project/vendor/ +0xa8
my-project/vendor/*InternalMessageInfo).Size(0xf9ef40, 0xae7fa0, 0xc000068cc0, 0x30448c0)
        D:/projects/golang/src/my-project/vendor/ +0x6e
my-project/vendor/my-protos.(*Document).XXX_Size(0xc000068cc0, 0xae7fa0)
        D:/projects/golang/src/my-project/vendor/my-protos/geofancy.pb.go:197 +0x4a
my-project/vendor/*Buffer).Marshal(0xc0002de698, 0xae7fa0, 0xc000068cc0, 0xc0000363f0, 0xc000068cc0)
        D:/projects/golang/src/my-project/vendor/ +0x8c
my-project/vendor/, 0xc000068cc0, 0xc0002de690, 0x0, 0x0, 0xc000006000, 0x99a900, 0x1)        
        D:/projects/golang/src/my-project/vendor/ +0xe9
my-project/vendor/, 0xc000068cc0, 0x0, 0x2030000, 0x2030000, 0x30000, 0x20)
        D:/projects/golang/src/my-project/vendor/ +0xb4
my-project/vendor/, 0xfbc400, 0xa0c520, 0xc000068cc0, 0xc000310020, 0xc000362000, 0x11d0008, 0x0, 0x0)       
        D:/projects/golang/src/my-project/vendor/ +0x59
my-project/vendor/, 0xc000068cc0, 0x3080168, 0xfbc400, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        D:/projects/golang/src/my-project/vendor/ +0x8c
my-project/vendor/*clientStream).SendMsg(0xc00032e000, 0xa0c520, 0xc000068cc0, 0x0, 0x0)
        D:/projects/golang/src/my-project/vendor/ +0x157
my-project/vendor/, 0xc000068f60, 0xa42207, 0x25, 0xa0c520, 0xc000068cc0, 0x9e3000, 0xc00003c840, 0xc000065180, 0x0, ...)
        D:/projects/golang/src/my-project/vendor/ +0xee
my-project/vendor/*ClientConn).Invoke(0xc000065180, 0xaed320, 0xc000068f60, 0xa42207, 0x25, 0xa0c520, 0xc000068cc0, 0x9e3000, 0xc00003c840, 0x0, ...)
        D:/projects/golang/src/my-project/vendor/ +0x1bb
my-project/vendor/my-protos.(*geofancyServiceClient).SetDocument(0xc000006030, 0xaed320, 0xc000068f60, 0xc000068cc0, 0x0, 0x0, 0x0, 0xc000065180, 0x0, 0x0)
        D:/projects/golang/src/my-project/vendor/my-protos/geofancy.pb.go:925 +0xd9
main.sendMyMessage(0xc0002e4000, 0x77359400)
        D:/projects/golang/src/my-project/main.go:89 +0x685
        D:/projects/golang/src/my-project/main.go:117 +0xf4
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • duanli6618 2019-08-21 00:00

    I am surprised your code is compiling. I was so intrigued that I generated the Go code in my environment to understand it.

    The "geofancy.Document" struct cannot receive a Point as a value for the attribute Geo because it expects a generic "Document Geo" (that could be a Document_Point, a Document_LineString, etc...)

    The auto generated code has an interface that you can use in this case.

        // add coordinate to a point
        point := geofancy.Document_Point{
            Point: &geofancy.Point{
                Coord: &coord,

    Now your variable point is an struct that implements an interface acceptable by Geo.

    document := geofancy.Document{
      Collection:   "some-collection",
      Id:           "some-id",
      Geo:          &point,

    I was not able to compile using your example because the was getting the error:

     cannot use &point (type **geofancy.Point) as type geofancy.isDocument_Geo in field value:
        **geofancy.Point does not implement geofancy.isDocument_Geo (missing geofancy.isDocument_Geo method)```
    打赏 评论

相关推荐 更多相似问题