-1

I like creating new types like that

type Category string
const (
  CategoryA Category = "A"
  CategoryB Category = "B"
  ...
)

type Object struct {
  Cat Category `json:"cat"`
}

I think this is a great thing to do when we have a limited choice of values for a variable. But I have some trouble to validate this kind of type because someone can do something like this (especially when we talk about REST API where the client doesn't have the server code):

s := Objecy{
  Cat : Category("not a valid category")
}

Is there a way to check the value of Object.Cat without using :

if s.Cat != CategoryA || s.Cat != CategoryB || ... {
 return false
}

Thanks for your answers

Quentin
  • 327
  • 3
  • 10
  • 1
    You may build a map (functioning as a set) from the valid values, and to check if its valid, you simply check if the value is in the map. – icza Aug 03 '23 at 08:39
  • You could use the map approach, as @icza suggested. Alternatively, you could create a custom `MarshalJSON` and `UnmarshalJSON` function on the `Category` type, and _not_ export it (ie change it to `category`), so callers can't cast random values to `Category`. It can be a useful approach to do this sometimes, but seeing as this is in a REST context, and you're getting your input from JSON, a map just makes sense. The difference here is that using custom marshalling allows you to validate while unmarshalling – Elias Van Ootegem Aug 03 '23 at 11:36
  • You could also use a bitmask where `CategoryA Category = 1 << iota` and have a local const as `validCategories Category = CategoryA | CategoryB | ...`, so you can validate the values with a simple bitwise operator. Add custom marshalling (to map the numeric values to a more human readable string) and you're good. This only matters if you want to support multiple values being combined (which is what bitwise operators are really useful for) – Elias Van Ootegem Aug 03 '23 at 11:42

0 Answers0