Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go build with protocol buffer error: too few values in struct initializer

I have a proto file:

syntax = "proto3";

package main;

message Client {
    int32 Id = 1;
    string Name = 2;
    string Email = 3;
}

The compiled Client struct like below:

type Client struct {
    Id                   int32    `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty"`
    Name                 string   `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
    Email                string   `protobuf:"bytes,3,opt,name=Email,proto3" json:"Email,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}

When I am trying to init this Client struct like below:

client := &Client{123, "John", "[email protected]"}

I am getting building error: too few values in struct initializer. I found a way to fix it by adding XXX_NoUnkeyedLiteral, XXX_unrecognized, XXX_sizecache. I don't know what these are, and wondering if this is the right way to do it:

client := &Client{123, "John", "[email protected]", struct{}{}, []byte{}, int32(0)}
like image 912
yong ho Avatar asked Aug 08 '18 08:08

yong ho


2 Answers

In struct composite literals you may omit the field names to which you list values for (this is called unkeyed literal), but then you have to list initial values for all fields and in their declaration order. Or you may use a keyed literal where you explicitly state which fields you specify initial values for. In the latter, you are allowed to omit any of the fields, you may just list the ones you want to give an initial value different from the field's zero value).

You used unkeyed composite literal, in which case you must list values for all fields, which you didn't. This is what the error message tells you: "too few values in struct initializer".

The field name (generated by protobuf) itself should give you the hint: XXX_NoUnkeyedLiteral. It suggests you should not use a composite literal without keys.

So use a composite literal with keys, like this::

client := &Client{
    Id:    123,
    Name:  "John",
    Email: "[email protected]",
}

This form is more readable, and it is immune to struct changes. E.g. if the Client struct would get new fields, or fields would get rearranged, this code would still be valid and compile.

like image 60
icza Avatar answered Nov 18 '22 05:11

icza


Add field name before the value can solve the building error, as

client := &Client{Id: 123, Name: "John", Email: "[email protected]"}

I find this out by checking the grpc golang example, but maybe somebody can explain why? ;)

like image 1
Penny Qian Avatar answered Nov 18 '22 06:11

Penny Qian