Check if value exists in enum - go

I have created a strict like the following in my app:
type Datatype int8
const (
user Datatype = iota
address
test
)
var datatypes = [...]string{"User", "Address", "Test"}
func (datatype Datatype) String() string {
return datatypes[datatype]
}
I would like to be able to validate a value passed via a command-line flag against this enum.
I thought I had seen something like dtype == Datatype being used, but I am apparently sorely mistaken.
If this is not possible I can go the route of putting these values in an array. However, I feel the enum approach is more elegant.

From your code sample it looks like you are trying to see if a map (rather than a struct) contains a particular key.
If so, the answer is here
A two-value assignment tests for the existence of a key:
i, ok := m["route"]
In this statement, the first value (i) is assigned
the value stored under the key "route". If that key doesn't exist, i
is the value type's zero value (0). The second value (ok) is a bool
that is true if the key exists in the map, and false if not.
To test for a key without retrieving the value, use an underscore in
place of the first value:
_, ok := m["route"]

Related

Operation applied on values of a type

As mentioned in Go specification:
"A type determines a set of values together with operations and methods specific to those values."
To introduce an operation or method to be applied on the values of a type,
Is that operation applied on values (taken from a set) supposed to give the result (or value) from the same set?
For example, in the below code, findName() is not supposed to be a method on type user. Instead findName() should be a helper function.
type user struct {
name string
email string
age int
}
func (u user) findElder(other user) user {
if u.age >= other.age {
return u
}
return other
}
func (u user) findName() string {
return u.name
}
"operations and methods specific to those values" does not mean that they are unique to those values, or that they result in those values.
According to Google, "specific" means "clearly defined or identified." In this quote from the Go spec, the word "specific" is used with regard to the fact that Go is strongly typed, meaning that operations and methods work on the types that they are defined or identified to work on.
For example, the == operator is specified to work on integer types, thus, the == operator is specific to values of int, int32, uint8, etc.
No, I don't think that the operation applied on values (taken from a set) are supposed to give the result (or value), only from the same set. They can be from a different set of values as well. It all depends on the use case, the design of the type and the operation.
So in your case, findName() can very well be a method even though it is returning something not in the set of input values.

assignment of function result

Coming from C#, this puzzles me.
In Go, if I have
type Employee struct {
ID int
Salary int
}
then I can do
var tom Employee
tom.Salary = 100
so far so good. Then if I have a function
func employeeByID(id int) Employee {
// do something and return an employee
}
Then why does this not compile?
employeeByID(10).Salary = 100
Moreover, this seems to compile fine:
andrew := employeeByID(10)
andrew.Salary = 100
It doesn't compile because that assignment is not valid.
Spec: Assignments:
Each left-hand side operand must be addressable, a map index expression, or (for = assignments only) the blank identifier.
The return values of function calls are not addressable. For details, see How to get the pointer of return value from function call? and How can I store reference to the result of an operation in Go?
Think about it: you call a function, it returns a value (which you don't store), what good would come from changing it if you don't store the result? It would be discarded, and so the assignment would also be useless.
If you store the result in a variable like in your second example, you can change its fields because variables are addressable.

struct initialization: too few values in p.U literal or implicit assignment of unexported field 'c' in p.U literal?

I am sorry for that simple question I have the following code
// package p
package p
// U type
type U struct {
A, B int
c int
} // A and B are exported only
// main
package main
import (
"fmt"
"./p"
)
func main() {
pp := p.U{A: 3, B: 4}
uu := p.U{3, 5} // the error resulted from this line
fmt.Println(pp)
fmt.Println(uu)
}
when I try to compile I get an error: too few values in p.U literal. I'm expecting that there no need to add c value. when I try to add the c value I get another expected error: implicit assignment of unexported field 'c' in p.U literal
You must keep the following rules in mind while creating a struct literal:
A key must be a field name declared in the struct type.
An element list that does not contain any keys must list an element for each struct field in the order in which the fields are declared.
An element list that contains keys does not need to have an element for each struct field. Omitted fields get the zero value for that field.
A literal may omit the element list; such a literal evaluates to the zero value for its type.
It is an error to specify an element for a non-exported field of a struct belonging to a different package.
In golang, there's to ways to instantiate structs: with keys and without keys.
When instantiating with keys, you would write the value of each field name next to the field name like such:
type Employee struct {
name string
age int
boss bool
}
employee := Employee{name: "John", age: 30}
When instantiating without keys, you just write the value of each field without writing the field names like such:
type Employee struct{
name string
age int
boss bool
}
employee := Employee{"John", 30, false}
As you might've noticed, when instantiating with keys, you don't have to specify a value for each field (you don't have to include a value for boss). This is because, since you're only giving values to specific fields, golang can assume the values for the other fields.
On the other hand, when instantiating without keys, you do have to specify a value for each field since, otherwise, if you didn't specify a value for each field, golang would not be able to assume which value goes to which field.
So, long story short, you can only instantiate structs without keys if you specify values for each field. Otherwise, you have to use keys and allow golang to assume the default values for the other fields.

Getting error while access the struct type of array element as undefined (type []ParentIDInfo has no field or method PCOrderID)

I am new to golang and I have one issue which I think community can help me to solve it.
I have one data structure like below
type ParentIDInfo struct {
PCOrderID string `json:"PCorderId",omitempty"`
TableVarieties TableVarietyDC `json:"tableVariety",omitempty"`
ProduceID string `json:"PRID",omitempty"`
}
type PCDCOrderAsset struct {
PcID string `json:"PCID",omitempty"`
DcID string `json:"DCID",omitempty"`
RequiredDate string `json:"requiredDate",omitempty"`
Qty uint64 `json:"QTY",omitempty"`
OrderID string `json:"ORDERID",omitempty"`
Status string `json:"STATUS",omitempty"`
Produce string `json:"Produce",omitempty"`
Variety string `json:"VARIETY",omitempty"`
Transports []TransportaionPCDC `json:"Transportaion",omitempty"`
ParentInfo []ParentIDInfo `json:"ParentInfo",omitempty"`
So I have issue to access the PCOrderID which inside the []ParentIDInfo . I have tried below however I getting error as "pcdcorder.ParentInfo.PCOrderID undefined (type []ParentIDInfo has no field or method PCOrderID)"
keyfarmercas = append(keyfarmercas, pcdcorder.ParentInfo.PCOrderID)
Any help will be very good
Thanks in advance
PCDCOrderAsset.ParentInfo is not a struct, it does not have a PCOrderID field. It's a slice (of element type ParentIDInfo), so its elements do, e.g. pcdcorder.ParentInfo[0].PCOrderID.
Whether this is what you want we can't tell. pcdcorder.ParentInfo[0].PCOrderID gives you the PCOrderID field of the first element of the slice. Based on your question this may or may not be what you want. You may want to append all IDs (one from each element). Also note that if the slice is empty (its length is 0), then pcdcorder.ParentInfo[0] would result in a runtime panic. You could avoid that by first checking its length and only index it if its not empty.
In case you'd want to add ids of all elements, you could use a for loop to do that, e.g.:
for i := range pcdorder.ParentInfo {
keyfarmercas = append(keyfarmercas, pcdcorder.ParentInfo[i].PCOrderID)
}

Properly distinguish between not set (nil) and blank/empty value

Whats the correct way in go to distinguish between when a value in a struct was never set, or is just empty, for example, given the following:
type Organisation struct {
Category string
Code string
Name string
}
I need to know (for example) if the category was never set, or was saved as blank by the user, should I be doing this:
type Organisation struct {
Category *string
Code *string
Name *string
}
I also need to ensure I correctly persist either null or an empty string to the database
I'm still learning GO so it is entirely possible my question needs more info.
The zero value for a string is an empty string, and you can't distinguish between the two.
If you are using the database/sql package, and need to distinguish between NULL and empty strings, consider using the sql.NullString type. It is a simple struct that keeps track of the NULL state:
type NullString struct {
String string
Valid bool // Valid is true if String is not NULL
}
You can scan into this type and use it as a query parameter, and the package will handle the NULL state for you.
Google's protocol buffers (https://code.google.com/p/goprotobuf/) use pointers to describe optional fields.
The generated objects provide GetFoo methods which take the pain away from testing for nil (a.GetFoo() returns an empty string if a.Foo is nil, otherwise it returns *a.Foo).
It introduces a nuisance when you want to write literal structs (in tests, for example), because &"something" is not valid syntax to generate a pointer to a string, so you need a helper function (see, for example, the source code of the protocol buffer library for proto.String).
// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
func String(v string) *string {
return &v
}
Overall, using pointers to represent optional fields is not without drawbacks, but it's certainly a viable design choice.
The standard database/sql package provides a NullString struct (members are just String string and Valid bool). To take care of some of the repetitive work of persistence, you could look at an object-relational manager like gorp.
I looked into whether there was some way to distinguish two kinds of empty string just out of curiosity, and couldn't find one. With []bytes, []byte{} == []byte(nil) currently returns false, but I'm not sure if the spec guarantees that to always remain true. In any case, it seems like the most practical thing to do is to go with the flow and use NullString.

Resources