golang / protobuf

Go support for Google's protocol buffers
BSD 3-Clause "New" or "Revised" License
9.66k stars 1.58k forks source link

Undefined enum number doesn't default to UNKNOWN #1516

Open Mido-sys opened 1 year ago

Mido-sys commented 1 year ago

What version of protobuf and what language are you using?

Protobuf v3 protoc-gen-go v1.28.1 protoc v3.15.8 Go 1.18.1

What did you do? PROTO File

message Product {
   enum STATUS{
      UNKNOWN =0;
      ACTIVE 1;
     DISABLED = 2;
  }

  STATUS product_status =1;
}

Golang Client

req := &pb.Product{}
req.ProductStatus = 100;

Golang Server

log.Println(req.ProductStatus == pb.Product_UNKNOWN) // Should be TRUE, but I get `100`

What did you expect to see? The req.ProductStatus should have a status of pb.Product_UNKNOWN, which is the default value when it can't match the value What did you see instead? I get 100 when I do in the server req.GetProductStatus() req.ProductStatus or req.GetProductStatus().String

puellanivis commented 1 year ago

This is working as intended:

During deserialization, unrecognized enum values will be preserved in the message, though how this is represented when the message is deserialized is language-dependent. In languages that support open enum types with values outside the range of specified symbols, such as C++ and Go, the unknown enum value is simply stored as its underlying integer representation.

https://developers.google.com/protocol-buffers/docs/proto3#enum

Mido-sys commented 1 year ago

@puellanivis, Thanks for getting back to me. Why can't the enum getter handle this? It already does return the default if x == nil?
So something like this

func (x *Product) GetStatus() Status {
  if x != nil {
    if _, ok := Status_value[int32(x.TransactionType)]; ok {
    return x.TransactionType
     }

   }
  return Product_UNKNOWN
}
puellanivis commented 1 year ago

It returns the default value if x == nil because the default value of a message is a message wherein all its fields are their default values. Thus the value of (*Product)(nil).GetStatus() would have to be the default value of the enum, which by proto3 is defined as the first entry, which must be = 0. That this is Product_UNKNOWN here, is merely a habit of convenience. But for a common case like enum MobileType { IOS = 0; ANDROID = 1; } the default value would then be IOS and not an undefined value.