8

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", "john@aol.com"}

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", "john@aol.com", struct{}{}, []byte{}, int32(0)}
icza
  • 389,944
  • 63
  • 907
  • 827
yong ho
  • 3,892
  • 9
  • 40
  • 81

2 Answers2

9

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: "john@aol.com",
}

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.

icza
  • 389,944
  • 63
  • 907
  • 827
  • Thanks for your answer. But it's not easy to write something like this in GoLand. Don't know how to change the settings. – yong ho Aug 10 '18 at 08:12
1

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

client := &Client{Id: 123, Name: "John", Email: "john@aol.com"}

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

Penny Qian
  • 386
  • 2
  • 4