Does type definition help assign restricted values? - go

In the below struct type:
type Employee struct {
Name string `json:"name"`
JobTitle JobTitleType `json:"jobtitle"`
}
member JobTitle should be ensured to have restricted(specific) values( of string type).
type JobTitleType string
const(
GradeATitle JobTitleType = "Clerk"
GradeBTitle JobTitleType = "Manager"
)
Does type definition(JobTitleType) help assign restricted values to member JobTitle?

No. You can assign any value to JobTitle:
e.JobTitle=JobTitleType("bogus")
The JobTitleType is based on string, so all string values can be converted to it.
You can use getter/setters to enforce runtime validation.

No, it will not restrict the values, any value that has type JobTitleType can be assigned to JobTitle. Currently, there is no enum type in Go. For restricting values you will probably need to write your own logic.

No, you should use it in the validation logic. For example, https://github.com/go-playground/validator has oneOf operator for validation.
Go don't have enum type, but you can do something like this
package main
import (
"fmt"
)
var JobTitleTypes = newJobTitleTypeRegistry()
func newJobTitleTypeRegistry() *jobTitleTypeRegistry{
return &jobTitleTypeRegistry{
GradeATitle : "Clerk",
GradeBTitle : "Manager",
}
}
type jobTitleTypeRegistrystruct {
GradeATitle string
GradeBTitle string
}
func main() {
fmt.Println(JobTitleTypes.GradeATitle)
}

Related

How can I choose which struct member to update at runtime?

Say I have a struct in Go that looks like this:
LastUpdate struct {
Name string `yaml:"name"`
Address string `yaml:"address"`
Phone string `yaml:"phone"`
}
Now say I want to create a function that accepts the name of the field (eg. "Phone") and then updates that field to a value, like today's date.
How can I build the function in a way that it will accept the name of the field and update that field in the struct?
I know that I could do an IF clause for each scenario (if field == "Phone") {var.LastUpdate.Phone = time.Now().Date()}, but I'd like to build this function so that I don't have to go add an IF clause every time I add a new member to this struct in the future. Thoughts?
Use the reflect package to set a field by name.
// setFieldByName sets field with given name to specified value.
// The structPtr argument must be a pointer to a struct. The
// value argument must be assignable to the field.
func setFieldByName(structPtr interface{}, name string, value interface{}) error {
v := reflect.ValueOf(structPtr)
v = v.Elem() // deference pointer
v = v.FieldByName(name) // get field with specified name
if !v.IsValid() {
return errors.New("field not found")
}
v.Set(reflect.ValueOf(value))
return nil
}
Use it like this:
var lu LastUpdate
setFieldByName(&lu, "Name", "Russ Cox")
Run it on the Playground

Defining a MongoDB Schema/Collection in mgo

I want to use mgo to create/save a MongoDB collection. But I would like to define it more extensively (for e.g to mention that one of the attribute is mandatory, another one is of an enum type and has a default value).
I have defined the struct like this, but don't know how to describe the constraints on it.
type Company struct {
Name string `json:"name" bson:"name"` // --> I WANT THIS TO BE MANDATORY
CompanyType string `json:"companyType" bson:"companyType"` // -->I WANT THIS TO BE AN ENUM
}
Is this possible to do in mgo, like how we can do it in MongooseJS?
mgo isn't an ORM or a validation tool. mgo is only an interface to MongoDB.
It's not bad to do validation all by yourself.
type CompanyType int
const (
CompanyA CompanyType = iota // this is the default
CompanyB CompanyType
CompanyC CompanyType
)
type Company struct {
Name string
CompanyType string
}
func (c Company) Valid() bool {
if c.Name == "" {
return false
}
// If it's a user input, you'd want to validate CompanyType's underlying
// integer isn't out of the enum's range.
if c.CompanyType < CompanyA || c.CompanyType > CompanyB {
return false
}
return true
}
Check this out for more about enums in Go.

How can I add a new boolean property to a Golang struct and set the default value to true?

I have a user struct that corresponds to an entity. How can I add a new property active and set the default value to true?
Can I also set the value of that property to true for all existing entities by some easy method?
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
Bonus questions: I don't quite understand the syntax in the struct. What do the three columns represent? What do the JSON strings have ``around them?
//You can't change declared type.
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
//Instead you construct a new one embedding existent
type ActiveUser struct {
User
Active bool
}
//you instantiate type literally
user := User{1, "John"}
//and you can provide constructor for your type
func MakeUserActive(u User) ActiveUser {
auser := ActiveUser{u, true}
return auser
}
activeuser := MakeUserActive(user)
You can see it works https://play.golang.org/p/UU7RAn5RVK
You have to set the default value as true at the moment when you are passing the struct type to a variable, but this means you need to extend that struct with a new Active field.
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
Active bool
}
user := User{1, "John", true}
json:"id" means that you are mapping the json decoded object field to the field id in your struct type. Practically you are deserialize the json string into object fields which later you can map to their specific field inside the struct.

How to specify a struct with a multi-column unique index for Gorm?

How do I define my structs to specify a multi-column unique index to Gorm in Go?
Such as:
type Something struct {
gorm.Model
First string `sql:"unique_index:unique_index_with_second"`
Second string `sql:"unique_index:unique_index_with_first"`
}
this is how you do it: You need to use the gorm struct tag and specify that the index is unique
type Something struct {
gorm.Model
First string `gorm:"index:idx_name,unique"`
Second string `gorm:"index:idx_name,unique"`
}
You can define same unique index for each column.
type Something struct {
gorm.Model
First string `sql:"unique_index:idx_first_second"`
Second string `sql:"unique_index:idx_first_second"`
}
for latest version of gorm (or for my case)
this works:
type Something struct {
gorm.Model
First string `gorm:"uniqueIndex:idx_first_second"`
Second string `gorm:"uniqueIndex:idx_first_second"`
}

How do I check if a outer type is a type of inner type?

If I have different forms of user structs being passed around my application is there a way to check if that embedded struct is a type of the outer struct?
type (
user struct {
name string
email string
}
admin struct {
user
level string
}
)
Depending on you need, you have two main methods: reflect.TypeOf, and the type swtich.
You will use the first to compare the type of an interface with another one. Example:
if reflect.TypeOf(a) == reflect.TypeOf(b) {
doSomething()
}
You will use the second to do a particular action given the type of an interface. Example:
switch a.(type) {
case User:
doSomething()
case Admin:
doSomeOtherThing()
}

Resources