├── README.md ├── go.mod ├── .gitmodules ├── Makefile ├── examples └── example_ping │ └── main.go ├── go.sum ├── main.go ├── ironhawk └── io.go ├── main_test.go └── wire └── cmd.pb.go /README.md: -------------------------------------------------------------------------------- 1 | dicedb-go 2 | === 3 | 4 | Go SDK for [DiceDB](https://github.com/dicedb/dice). 5 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/dicedb/dicedb-go 2 | 3 | go 1.23.5 4 | 5 | require google.golang.org/protobuf v1.36.4 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "protos"] 2 | path = protos 3 | url = https://github.com/dicedb/dicedb-protos.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GOLANGCI_LINT_VERSION := 1.60.1 2 | 3 | lint: 4 | gofmt -w . 5 | golangci-lint run ./... 6 | 7 | generate: 8 | protoc --go_out=. --go-grpc_out=. protos/cmd.proto 9 | 10 | test: 11 | go test -v ./... 12 | -------------------------------------------------------------------------------- /examples/example_ping/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dicedb/dicedb-go" 7 | "github.com/dicedb/dicedb-go/wire" 8 | ) 9 | 10 | func main() { 11 | client, err := dicedb.NewClient("localhost", 7379) 12 | if err != nil { 13 | fmt.Println(err) 14 | } 15 | 16 | resp := client.Fire(&wire.Command{Cmd: "PING"}) 17 | fmt.Println(resp) 18 | } 19 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= 2 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 3 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 4 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 5 | google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= 6 | google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 7 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package dicedb 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "time" 7 | 8 | "github.com/dicedb/dicedb-go/ironhawk" 9 | "github.com/dicedb/dicedb-go/wire" 10 | ) 11 | 12 | type Client struct { 13 | conn net.Conn 14 | } 15 | 16 | func newConn(host string, port int) (net.Conn, error) { 17 | addr := fmt.Sprintf("%s:%d", host, port) 18 | conn, err := net.DialTimeout("tcp", addr, 5*time.Second) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return conn, nil 23 | } 24 | 25 | func NewClient(host string, port int) (*Client, error) { 26 | conn, err := newConn(host, port) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return &Client{conn: conn}, nil 31 | } 32 | 33 | func (c *Client) Fire(cmd *wire.Command) *wire.Response { 34 | if err := ironhawk.Write(c.conn, cmd); err != nil { 35 | return &wire.Response{ 36 | Err: err.Error(), 37 | } 38 | } 39 | 40 | resp, err := ironhawk.Read(c.conn) 41 | if err != nil { 42 | return &wire.Response{ 43 | Err: err.Error(), 44 | } 45 | } 46 | 47 | return resp 48 | } 49 | 50 | func (c *Client) Close() { 51 | c.conn.Close() 52 | } 53 | -------------------------------------------------------------------------------- /ironhawk/io.go: -------------------------------------------------------------------------------- 1 | package ironhawk 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "net" 8 | "time" 9 | 10 | "github.com/dicedb/dicedb-go/wire" 11 | "google.golang.org/protobuf/proto" 12 | ) 13 | 14 | const ( 15 | maxRequestSize = 32 * 1024 * 1024 // 32 MB 16 | ioBufferSize = 16 * 1024 // 16 KB 17 | idleTimeout = 30 * time.Minute 18 | ) 19 | 20 | func Read(conn net.Conn) (*wire.Response, error) { 21 | var result []byte 22 | reader := bufio.NewReaderSize(conn, ioBufferSize) 23 | buf := make([]byte, ioBufferSize) 24 | 25 | for { 26 | n, err := reader.Read(buf) 27 | if n > 0 { 28 | if len(result)+n > maxRequestSize { 29 | return nil, fmt.Errorf("request too large") 30 | } 31 | result = append(result, buf[:n]...) 32 | } 33 | if err != nil { 34 | if err == io.EOF { 35 | break 36 | } 37 | return nil, err 38 | } 39 | 40 | if n < len(buf) { 41 | break 42 | } 43 | } 44 | 45 | if len(result) == 0 { 46 | return nil, io.EOF 47 | } 48 | 49 | r := &wire.Response{} 50 | if err := proto.Unmarshal(result, r); err != nil { 51 | return nil, fmt.Errorf("failed to unmarshal command: %w", err) 52 | } 53 | return r, nil 54 | } 55 | 56 | func Write(conn net.Conn, c *wire.Command) error { 57 | data, err := proto.Marshal(c) 58 | if err != nil { 59 | return err 60 | } 61 | _, err = conn.Write(data) 62 | return err 63 | } 64 | -------------------------------------------------------------------------------- /main_test.go: -------------------------------------------------------------------------------- 1 | package dicedb 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "testing" 7 | 8 | "github.com/dicedb/dicedb-go/wire" 9 | ) 10 | 11 | func areResponseValuesEqual(r1, r2 *wire.Response) bool { 12 | switch r1.Value.(type) { 13 | case *wire.Response_VStr: 14 | return r1.Value.(*wire.Response_VStr).VStr == r2.Value.(*wire.Response_VStr).VStr 15 | case *wire.Response_VInt: 16 | return r1.Value.(*wire.Response_VInt).VInt == r2.Value.(*wire.Response_VInt).VInt 17 | case *wire.Response_VFloat: 18 | return r1.Value.(*wire.Response_VFloat).VFloat == r2.Value.(*wire.Response_VFloat).VFloat 19 | case *wire.Response_VBytes: 20 | return bytes.Equal(r1.Value.(*wire.Response_VBytes).VBytes, r2.Value.(*wire.Response_VBytes).VBytes) 21 | case *wire.Response_VNil: 22 | return r1.Value.(*wire.Response_VNil) == r2.Value.(*wire.Response_VNil) 23 | } 24 | return false 25 | } 26 | 27 | func TestNewClient(t *testing.T) { 28 | tests := []struct { 29 | name string 30 | host string 31 | port int 32 | wantNil bool 33 | err error 34 | }{ 35 | { 36 | name: "valid connection", 37 | host: "localhost", 38 | port: 7379, 39 | wantNil: false, 40 | err: nil, 41 | }, 42 | { 43 | name: "invalid port", 44 | host: "localhost", 45 | port: -1, 46 | wantNil: true, 47 | err: errors.New("dial tcp: address -1: invalid port"), 48 | }, 49 | { 50 | name: "unable to connect", 51 | host: "localhost", 52 | port: 9999, 53 | wantNil: true, 54 | err: errors.New("dial tcp 127.0.0.1:9999: connect: connection refused"), 55 | }, 56 | } 57 | 58 | for _, tt := range tests { 59 | t.Run(tt.name, func(t *testing.T) { 60 | client, err := NewClient(tt.host, tt.port) 61 | if (client == nil) != tt.wantNil { 62 | t.Errorf("NewClient() got = %v, %s, want nil = %v, err = %v", client, err, tt.wantNil, tt.err) 63 | } 64 | if err != nil && err.Error() != tt.err.Error() { 65 | t.Errorf("NewClient() got = %v, %s, want nil = %v, err = %v", client, err, tt.wantNil, tt.err) 66 | } 67 | }) 68 | } 69 | } 70 | 71 | func TestClient_Fire(t *testing.T) { 72 | client, err := NewClient("localhost", 7379) 73 | if err != nil { 74 | t.Fatalf("failed to create client: %v", err) 75 | } 76 | 77 | tests := []struct { 78 | name string 79 | mockConn *Client 80 | cmd *wire.Command 81 | result *wire.Response 82 | err error 83 | }{ 84 | { 85 | name: "successful command", 86 | mockConn: client, 87 | cmd: &wire.Command{Cmd: "PING"}, 88 | result: &wire.Response{Value: &wire.Response_VStr{VStr: "PONG"}}, 89 | err: nil, 90 | }, 91 | } 92 | 93 | for _, tt := range tests { 94 | t.Run(tt.name, func(t *testing.T) { 95 | resp := tt.mockConn.Fire(tt.cmd) 96 | if tt.err != nil && resp.Err != tt.err.Error() { 97 | t.Errorf("Fire() expected error: %v, want: %v", resp.Err, tt.err) 98 | } 99 | if !areResponseValuesEqual(resp, tt.result) { 100 | t.Errorf("Fire() unexpected response: %v, want: %v", resp, tt.result) 101 | } 102 | }) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /wire/cmd.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.36.4 4 | // protoc v3.21.12 5 | // source: protos/cmd.proto 6 | 7 | package wire 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | structpb "google.golang.org/protobuf/types/known/structpb" 13 | reflect "reflect" 14 | sync "sync" 15 | unsafe "unsafe" 16 | ) 17 | 18 | const ( 19 | // Verify that this generated code is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 21 | // Verify that runtime/protoimpl is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 23 | ) 24 | 25 | type Command struct { 26 | state protoimpl.MessageState `protogen:"open.v1"` 27 | Cmd string `protobuf:"bytes,1,opt,name=cmd,proto3" json:"cmd,omitempty"` 28 | Args []string `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"` 29 | unknownFields protoimpl.UnknownFields 30 | sizeCache protoimpl.SizeCache 31 | } 32 | 33 | func (x *Command) Reset() { 34 | *x = Command{} 35 | mi := &file_protos_cmd_proto_msgTypes[0] 36 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 37 | ms.StoreMessageInfo(mi) 38 | } 39 | 40 | func (x *Command) String() string { 41 | return protoimpl.X.MessageStringOf(x) 42 | } 43 | 44 | func (*Command) ProtoMessage() {} 45 | 46 | func (x *Command) ProtoReflect() protoreflect.Message { 47 | mi := &file_protos_cmd_proto_msgTypes[0] 48 | if x != nil { 49 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 50 | if ms.LoadMessageInfo() == nil { 51 | ms.StoreMessageInfo(mi) 52 | } 53 | return ms 54 | } 55 | return mi.MessageOf(x) 56 | } 57 | 58 | // Deprecated: Use Command.ProtoReflect.Descriptor instead. 59 | func (*Command) Descriptor() ([]byte, []int) { 60 | return file_protos_cmd_proto_rawDescGZIP(), []int{0} 61 | } 62 | 63 | func (x *Command) GetCmd() string { 64 | if x != nil { 65 | return x.Cmd 66 | } 67 | return "" 68 | } 69 | 70 | func (x *Command) GetArgs() []string { 71 | if x != nil { 72 | return x.Args 73 | } 74 | return nil 75 | } 76 | 77 | type Response struct { 78 | state protoimpl.MessageState `protogen:"open.v1"` 79 | Err string `protobuf:"bytes,1,opt,name=err,proto3" json:"err,omitempty"` 80 | // Types that are valid to be assigned to Value: 81 | // 82 | // *Response_VNil 83 | // *Response_VInt 84 | // *Response_VStr 85 | // *Response_VFloat 86 | // *Response_VBytes 87 | Value isResponse_Value `protobuf_oneof:"value"` 88 | Attrs *structpb.Struct `protobuf:"bytes,7,opt,name=attrs,proto3" json:"attrs,omitempty"` 89 | unknownFields protoimpl.UnknownFields 90 | sizeCache protoimpl.SizeCache 91 | } 92 | 93 | func (x *Response) Reset() { 94 | *x = Response{} 95 | mi := &file_protos_cmd_proto_msgTypes[1] 96 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 97 | ms.StoreMessageInfo(mi) 98 | } 99 | 100 | func (x *Response) String() string { 101 | return protoimpl.X.MessageStringOf(x) 102 | } 103 | 104 | func (*Response) ProtoMessage() {} 105 | 106 | func (x *Response) ProtoReflect() protoreflect.Message { 107 | mi := &file_protos_cmd_proto_msgTypes[1] 108 | if x != nil { 109 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 110 | if ms.LoadMessageInfo() == nil { 111 | ms.StoreMessageInfo(mi) 112 | } 113 | return ms 114 | } 115 | return mi.MessageOf(x) 116 | } 117 | 118 | // Deprecated: Use Response.ProtoReflect.Descriptor instead. 119 | func (*Response) Descriptor() ([]byte, []int) { 120 | return file_protos_cmd_proto_rawDescGZIP(), []int{1} 121 | } 122 | 123 | func (x *Response) GetErr() string { 124 | if x != nil { 125 | return x.Err 126 | } 127 | return "" 128 | } 129 | 130 | func (x *Response) GetValue() isResponse_Value { 131 | if x != nil { 132 | return x.Value 133 | } 134 | return nil 135 | } 136 | 137 | func (x *Response) GetVNil() bool { 138 | if x != nil { 139 | if x, ok := x.Value.(*Response_VNil); ok { 140 | return x.VNil 141 | } 142 | } 143 | return false 144 | } 145 | 146 | func (x *Response) GetVInt() int64 { 147 | if x != nil { 148 | if x, ok := x.Value.(*Response_VInt); ok { 149 | return x.VInt 150 | } 151 | } 152 | return 0 153 | } 154 | 155 | func (x *Response) GetVStr() string { 156 | if x != nil { 157 | if x, ok := x.Value.(*Response_VStr); ok { 158 | return x.VStr 159 | } 160 | } 161 | return "" 162 | } 163 | 164 | func (x *Response) GetVFloat() float64 { 165 | if x != nil { 166 | if x, ok := x.Value.(*Response_VFloat); ok { 167 | return x.VFloat 168 | } 169 | } 170 | return 0 171 | } 172 | 173 | func (x *Response) GetVBytes() []byte { 174 | if x != nil { 175 | if x, ok := x.Value.(*Response_VBytes); ok { 176 | return x.VBytes 177 | } 178 | } 179 | return nil 180 | } 181 | 182 | func (x *Response) GetAttrs() *structpb.Struct { 183 | if x != nil { 184 | return x.Attrs 185 | } 186 | return nil 187 | } 188 | 189 | type isResponse_Value interface { 190 | isResponse_Value() 191 | } 192 | 193 | type Response_VNil struct { 194 | VNil bool `protobuf:"varint,2,opt,name=v_nil,json=vNil,proto3,oneof"` 195 | } 196 | 197 | type Response_VInt struct { 198 | VInt int64 `protobuf:"varint,3,opt,name=v_int,json=vInt,proto3,oneof"` 199 | } 200 | 201 | type Response_VStr struct { 202 | VStr string `protobuf:"bytes,4,opt,name=v_str,json=vStr,proto3,oneof"` 203 | } 204 | 205 | type Response_VFloat struct { 206 | VFloat float64 `protobuf:"fixed64,5,opt,name=v_float,json=vFloat,proto3,oneof"` 207 | } 208 | 209 | type Response_VBytes struct { 210 | VBytes []byte `protobuf:"bytes,6,opt,name=v_bytes,json=vBytes,proto3,oneof"` 211 | } 212 | 213 | func (*Response_VNil) isResponse_Value() {} 214 | 215 | func (*Response_VInt) isResponse_Value() {} 216 | 217 | func (*Response_VStr) isResponse_Value() {} 218 | 219 | func (*Response_VFloat) isResponse_Value() {} 220 | 221 | func (*Response_VBytes) isResponse_Value() {} 222 | 223 | var File_protos_cmd_proto protoreflect.FileDescriptor 224 | 225 | var file_protos_cmd_proto_rawDesc = string([]byte{ 226 | 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x63, 0x6d, 0x64, 0x2e, 0x70, 0x72, 0x6f, 227 | 0x74, 0x6f, 0x12, 0x04, 0x77, 0x69, 0x72, 0x65, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 228 | 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 229 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x2f, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 230 | 0x64, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 231 | 0x63, 0x6d, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 232 | 0x09, 0x52, 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0xcf, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 233 | 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 234 | 0x09, 0x52, 0x03, 0x65, 0x72, 0x72, 0x12, 0x15, 0x0a, 0x05, 0x76, 0x5f, 0x6e, 0x69, 0x6c, 0x18, 235 | 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x04, 0x76, 0x4e, 0x69, 0x6c, 0x12, 0x15, 0x0a, 236 | 0x05, 0x76, 0x5f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x04, 237 | 0x76, 0x49, 0x6e, 0x74, 0x12, 0x15, 0x0a, 0x05, 0x76, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x04, 0x20, 238 | 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x76, 0x53, 0x74, 0x72, 0x12, 0x19, 0x0a, 0x07, 0x76, 239 | 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x06, 240 | 0x76, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x07, 0x76, 0x5f, 0x62, 0x79, 0x74, 0x65, 241 | 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x06, 0x76, 0x42, 0x79, 0x74, 0x65, 242 | 0x73, 0x12, 0x2d, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 243 | 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 244 | 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 245 | 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x77, 246 | 0x69, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 247 | }) 248 | 249 | var ( 250 | file_protos_cmd_proto_rawDescOnce sync.Once 251 | file_protos_cmd_proto_rawDescData []byte 252 | ) 253 | 254 | func file_protos_cmd_proto_rawDescGZIP() []byte { 255 | file_protos_cmd_proto_rawDescOnce.Do(func() { 256 | file_protos_cmd_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_protos_cmd_proto_rawDesc), len(file_protos_cmd_proto_rawDesc))) 257 | }) 258 | return file_protos_cmd_proto_rawDescData 259 | } 260 | 261 | var file_protos_cmd_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 262 | var file_protos_cmd_proto_goTypes = []any{ 263 | (*Command)(nil), // 0: wire.Command 264 | (*Response)(nil), // 1: wire.Response 265 | (*structpb.Struct)(nil), // 2: google.protobuf.Struct 266 | } 267 | var file_protos_cmd_proto_depIdxs = []int32{ 268 | 2, // 0: wire.Response.attrs:type_name -> google.protobuf.Struct 269 | 1, // [1:1] is the sub-list for method output_type 270 | 1, // [1:1] is the sub-list for method input_type 271 | 1, // [1:1] is the sub-list for extension type_name 272 | 1, // [1:1] is the sub-list for extension extendee 273 | 0, // [0:1] is the sub-list for field type_name 274 | } 275 | 276 | func init() { file_protos_cmd_proto_init() } 277 | func file_protos_cmd_proto_init() { 278 | if File_protos_cmd_proto != nil { 279 | return 280 | } 281 | file_protos_cmd_proto_msgTypes[1].OneofWrappers = []any{ 282 | (*Response_VNil)(nil), 283 | (*Response_VInt)(nil), 284 | (*Response_VStr)(nil), 285 | (*Response_VFloat)(nil), 286 | (*Response_VBytes)(nil), 287 | } 288 | type x struct{} 289 | out := protoimpl.TypeBuilder{ 290 | File: protoimpl.DescBuilder{ 291 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 292 | RawDescriptor: unsafe.Slice(unsafe.StringData(file_protos_cmd_proto_rawDesc), len(file_protos_cmd_proto_rawDesc)), 293 | NumEnums: 0, 294 | NumMessages: 2, 295 | NumExtensions: 0, 296 | NumServices: 0, 297 | }, 298 | GoTypes: file_protos_cmd_proto_goTypes, 299 | DependencyIndexes: file_protos_cmd_proto_depIdxs, 300 | MessageInfos: file_protos_cmd_proto_msgTypes, 301 | }.Build() 302 | File_protos_cmd_proto = out.File 303 | file_protos_cmd_proto_goTypes = nil 304 | file_protos_cmd_proto_depIdxs = nil 305 | } 306 | --------------------------------------------------------------------------------