How to display all records using struct - go

I am trying to fetch all data from a table. It returns all data but it is displaying only the last record. I am using GORM and GIN with Golang.
I tried to create a struct and pass that struct to the Find method.
type MpCountry struct{
id uint
Iso string
Name string
Nicename string
Iso3 string
Numcode uint
phonecode uint
}
Code:
countries:= DbModel.MpCountry{}
DbModel.DB.Debug().Find(&countries)
fmt.Println(countries)
fmt.Println("test")
log.Printf("%+v", countries)
return &countries
Output
SELECT * FROM `mp_countries`
[239 rows affected or returned ]
{id:0 Iso:ZW Name:ZIMBABWE Nicename:Zimbabwe Iso3:ZWE Numcode:716 phonecode:0}

You are only passing in a struct, not a slice of structs. It is therefore replacing the values in the struct, until it reaches the last record.
Instead, pass in a pointer to a slice:
countries := &[]DbModel.MpCountry{}
DbModel.DB.Debug().Find(countries)

Related

Reflection to get field tag

In Go is there a good way to use reflection to get a field tag by just wrapping a field in a function from the reflect library?
I am basically trying to create a thin data access object that allows be to get the column name in the db without hard coding it all over the place.
Below is the struct with db column names as tags.
// Table Structures
type CusipTableRow struct {
Id int64 `db:"id"`
Cusip string `db:"cusip"`
Symbol string `db:"symbol"`
Active int8 `db:"active"`
Added_Time int32 `db:"added_timestamp"`
Description string `db:"description"`
Exchange string `db:"exchange"`
AssetType string `db:"asset_type"`
}
I am seeking a suggestion other than downloading another library on how to use reflection to essentially make a call like this to return a string with the tag value.
var row CusipTableRow
row.GetColumnName(row.Id) //Return column name based on tag.
I was considering possibly trying to use a map[address] fieldTag, but did not have luck getting that to work perhaps due to not fully having a grasp of the unsafe package. If that approach would have worked I was thinking a call like this could have worked:
row.GetColumnName(&row.Id) //Return column name based on tag.
You can get field tag given the address of the struct and the address of the field. Unsafe shenanigans are not required.
func GetColumnName(pstruct interface{}, pfield interface{}) string {
v := reflect.ValueOf(pstruct).Elem()
for i := 0; i < v.NumField(); i++ {
if v.Field(i).Addr().Interface() == pfield {
return v.Type().Field(i).Tag.Get("db")
}
}
panic("field not in struct")
}
Example use:
var v CusipTableRow
fmt.Println(GetColumnName(&v, &v.Added_Time)) // prints added_timestamp
Run it on the Go Playground.

How to fetch last record in gorm?

I'm working on a golang application in which I need to fetch last record from the table so I'm not able to do it. I have models mention below:-
type SQLTransaction struct {
Id int `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Version uint64 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty" gorm:"primaryKey"`
Hash string `protobuf:"bytes,3,opt,name=hash,proto3" json:"hash,omitempty"`
VmStatusId int `protobuf:"bytes,6,opt,name=vm_status_id,proto3" json:"vm_status_id,omitempty"`
}
Here is my gorm function in which I want to fetch the last record
func (mgr *manager) GetLastTxn() (int, error) {
var versionId int
resp := mgr.connection.Table("transactions").Last("", "version")
return versionId, resp.Error
}
Error:-
model value required
[0.053ms] [rows:0] SELECT * FROM `transactions` WHERE version ORDER BY `transactions`. DESC LIMIT 1
0 model value required
How can I achieve it please any help. Thanks in advance.
There are a couple of issues in your example that should be handled.
First, the error model value required suggests that the Last method needs a model to store the result. If you want the entire record with all the data you can do it like this:
var lastVersion SQLTransaction
resp := mgr.connection.Table("transactions").Last(&lastVersion)
If you only want the ID of the record, you do something like this:
var lastVersion struct {
ID int
}
resp := mgr.connection.Table("transactions").Last(&lastVersion)
Next, you don't need Last("", "version") because it doesn't do what you think it does. The first parameter is a pointer to your resulting object (which for all go-gorm methods always should be an object or a slice). The second one is a condition for the WHERE clause. So the correct syntax, if you don't need an additional WHERE clause, is:
resp := mgr.connection.Table("transactions").Last(&lastVersion)
If you look at the code of the Last method, it considers the primary key when it executes the method, so you don't even need any additional parameters or conditions.

How to convert map[string][]byte to map[string]interface{}

I have a function that excepts parameter of type map[string]interface{} but I have variable of type map[string][]byte. my question is how can I convert map[string][]byte to map[string]interface{} in Go.
This is a common miss-expectation from go. In this case each element of the map needs to be converted to interface.
So here's a workaround with sample code:
func foo(arg map[string]interface{}){
fmt.Println(arg)
}
// msaToMsi convert map string array of byte to map string interface
func msaToMsi(msa map[string][]byte) map[string]interface{}{
msi := make(map[string]interface{}, len(msa))
for k, v := range msa {
msi[k] = v
}
return msi
}
func main() {
msa := map[string][]byte{"a": []byte("xyz")}
foo(msaToMsi(msa))
}
The solution would be similar for the following map or array conversion as well:
map[string]string to map[string]interface{}
[]string to [] interface {}
Etc..
Ok so to answer your question an interface in GO can be used where you are passing or receiving a object/struct of where you are not sure of its type.
For example:
type Human struct {
Name string
Age int
School string
DOB time.Time
}
type Animal struct {
Name string
HasTail bool
IsMamal bool
DOB time.Time
}
func DisplayData(dataType interface{}, data byte)
This Display Data function can Display any type of data, it takes data and a struct both of which the function doesn't know until we pass them in... The data could be a Human or an Animal, both having different values which can be mapped depending on which interface we pass to the function...
This means we can reuse the code to display any data as long as we tell the function the data type we want to map the data to and display (i.e. Animal or Human...)
In your case the solution would be to define the data type, the structure of the data in the byte as a struct and where you make the map instead of map[string][]byte
try changing to
map[string]YourDefinedStructure
and pass that to the function that accepts map[string]interface{}.
Hopefully this helps, the question although you supply data types is rather vague as a use case and nature of the function that accepts map[string]interface{} can affect the approach taken.
You don't really have to convert while passing your map[string][]byte to the function.
The conversion needs to happen at the point where you want to use the value from the map.

Parse and validate "key1:value1; key2:value2" string to Go struct efficiently?

I have a "key1:value1; key2:value2" like string (string with key:value pattern concated by ;).
Now I wish to parse this string to a Go struct:
type CustomStruct struct {
KeyName1 string `name:"key1" somevalidation:"xxx"`
KeyName2 int `name:"key2" somevalidation:"yyy"`
}
In the above example, the struct tag defines the name of the key in the string and can provide some validation for its corresponding value (it can set a default value if validation fails). For instance, KeyName2 is an int value, so I wish the somevalidation can check whether the KeyName2 satisfy, let's say, greater than 30 and less equal than 100.
And in another senario, I can define another struct CustomStruct2 for string like key3:value3; key4:value4;
How can I archive this kind of requirement efficiently and elegantly?
I'll assume that you can parse the data to a map[string]interface{}.
Use the reflect package to set the fields. Here's the basic function:
// set sets fields in struct pointed to by pv to values in data.
func set(pv interface{}, data map[string]interface{}) {
// pv is assumed to be pointer to a struct
s := reflect.ValueOf(pv).Elem()
// Loop through fields
t := s.Type()
for i := 0; i < t.NumField(); i++ {
// Set field if there's a data value for the field.
f := t.Field(i)
if d, ok := data[f.Tag.Get("name")]; ok {
s.Field(i).Set(reflect.ValueOf(d))
}
}
}
This code assumes that the values in the data map are assignable to the corresponding field in the struct and that the first argument is a pointer to a struct. The code will panic if these assumptions are not true. You can protect against this by checking types and assignability using the reflect package.
playground example

Golang struct {}{} meaning

I am looking at the docs for the chi package. I see something like:
https://github.com/pressly/chi/blob/master/_examples/rest/main.go#L154
data := struct {
*Article
OmitID interface{} `json:"id,omitempty"` // prevents 'id' from being overridden
}{Article: article}
How do I interpret this? 2 parts I don't fully understand
How does the OmitID part prevent id from being set?
What does the {Article: article} part do?
The first {} in the struct definition is for define the field or attribute of that struct.
data := struct {
*Article
OmitID interface{} `json:"id,omitempty"` // prevents 'id' from being overridden
}
So the data is a struct that has fields *Article and OmitID with their respected type.
What does the {Article: article} part do?
the second {} is for defining the value of that field.
{Article: article}
this part is defining the value of Article field.
How does the OmitID part prevent id from being set?
In go you can define any number of field in the struct.
And you can call define it by calling the field and the value with the respected type. for example if I have this struct :
type DriverData struct {
Name string `json:"name"`
Status bool `json:"status"`
Location GeoJson `json:"location"`
}
I can call it like this :
example := DriverData{Name : "SampleName"}
the rest of the field will have zero values based on their respective data types.
You can read about golang Zero Values here

Resources