Set fields using Reflection - go

I am struggling with some Go lang code for a few days. I have a golang function that would set all the common fields like createdBy, updatedBy, etc inside a struct. I have googled a lot and have come up with the following code.
package main
import (
"fmt"
"reflect"
"time"
"strings"
)
type User struct {
UserId string `json:"userId"`
ObjectType string `json:"objectType"`
CreationDate string `json:"creationDate"`
UpdationDate string `json:"updationDate"`
Version int `json:"version"`
}
func main() {
//fmt.Println("Hello, playground")
var user = User{}
var k = setCommonParam(&user )
var p = k.(*User)
fmt.Println(p.CreationDate)
var l = *p
fmt.Println(l.ObjectType)
fmt.Println(reflect.TypeOf(k))
fmt.Println(reflect.TypeOf(user))
}
func setCommonParam(obj interface{}) (interface{}) {
entityValue := reflect.ValueOf(obj).Elem()
entityType := entityValue.Type()
for i:=0; i<entityValue.NumField(); i++ {
typeField := entityType.Field(i)
vField := entityValue.Field(i)
if typeField.Name == "ObjectType" {
vField.SetString(strings.ToLower(reflect.TypeOf(obj).Elem().Name()))
} else if typeField.Name == "CreationDate" {
vField.SetString(time.Now().Format(time.RFC3339))
} else if typeField.Name == "UpdationDate" {
vField.SetString(time.Now().Format(time.RFC3339))
} else if typeField.Name == "CreatedBy" {
} else if typeField.Name == "UpdatedBy" {
} else if typeField.Name == "Version" {
}
}
return obj
}
Is there any way I can write the following in a single line?
var k = setCommonParam(&user )
var p = k.(*User)
var l = *p
and do something like this:
user = setCommonParam(user)
I am sorry but I am new to this. Thanks.

If your question is "how to condense these 3 lines into one?", then the answer is:
var l = *(setCommonParam(&user).(*User))

Related

Iterate fields of different structures in one array

I want to iterate fields of different structures in one array
i try to do it like this
package main
import "fmt"
func main() {
m := msh{"hshHeader"}
p := pid{"pidHeader"}
var i []EmptyInterface
i = append(i, m)
i = append(i, p)
for _, emptyInterface := range i {
fmt.Println(emptyInterface.header)
}
}
type msh struct {
header string
}
type pid struct {
header string
}
type EmptyInterface interface {
}
As expected, on line 15 I get the message "Unresolved reference 'header'".
Do I understand correctly that in Go I should do this using methods
package main
import "fmt"
func main() {
m := msh{"hshHeader"}
p := pid{"pidHeader"}
var i []EmptyInterface
i = append(i, m)
i = append(i, p)
for _, NotEmptyInterface := range i {
fmt.Println(NotEmptyInterface.PrintHeader())
}
}
type msh struct {
header string
}
func (m msh) PrintHeader() string {
return m.header
}
type pid struct {
header string
}
func (p pid) PrintHeader() string {
return p.header
}
type EmptyInterface interface {
PrintHeader() string
}
I don’t know what else to add so that the bot on the site does not throw an error "It looks like your post is mostly code; please add some more details.", I can suggest reading again.

how to using reflect to create parametric entity

package main
import (
"fmt"
"reflect"
)
type Aservice struct {
}
type Adata struct {
msg string
}
type Bdata struct {
more string
}
var amap map[string]interface{} = make(map[string]interface{}, 1024)
func (aser *Aservice) Bar(data *Adata) error {
return nil
}
func (aser *Aservice) Foo(data *Bdata) error {
return nil
}
func main() {
var ser *Aservice
typeOfService := reflect.TypeOf(ser)
valueOfService := reflect.ValueOf(ser)
for i := 0; i < valueOfService.NumMethod(); i++ {
nref := valueOfService.Method(i).Type().In(0)
fmt.Println("++", nref.Elem().Name())
amap[typeOfService.Method(i).Name] = nref
}
}
Currently "Adata" and "Bdata" can be printed correctly
But I don’t know how to store the empty structure pointers of "Adata" and "Bdata" in amap
No idea for the next step
I want to use Method(i).Name() in amap to store the parameters that need to be passed in for the Method
Based on the suggestions in comments :
package main
import (
"fmt"
"reflect"
)
type Aservice struct {
}
type Adata struct {
msg string
}
type Bdata struct {
more string
}
var amap = map[string]interface{}{}
func (aser *Aservice) Bar(data *Adata) error {
return nil
}
func (aser *Aservice) Foo(data *Bdata) error {
return nil
}
func main() {
var ser *Aservice
typeOfService := reflect.TypeOf(ser)
valueOfService := reflect.ValueOf(ser)
for i := 0; i < valueOfService.NumMethod(); i++ {
nref := valueOfService.Method(i).Type().In(0)
amap[typeOfService.Method(i).Name] = reflect.New(nref.Elem()).Interface()
}
for k, v := range amap {
fmt.Printf("%s %#v\n", k, v)
}
}
Output:
Bar &main.Adata{msg:""}
Foo &main.Bdata{more:""}

GO store value froom LOOP

package main
import "fmt"
func main() {
var kata, kosong, kebalikan string
fmt.Print("Kata :")
fmt.Scan(&kata)
panjang := len(kata)
for i := panjang - 1; i >= 0; i-- {
kebalikan := kosong + fmt.Print(string(kata[i]))
}
if kata == kebalikan {
fmt.Println("\n", true)
} else {
fmt.Println("\n", false)
}
}
does anybody know how to store kosong + fmt.Print(string(kata[i])) to kebalikan ? just new in golang
the error is multiple-value fmt.Print() in single-value context
There are two problems with your code.
You need to use fmt.Sprint instead of fmt.Print in your case. The former returns a string, the latter prints it to stdout.
Do not use : in kebalikan := kosong + fmt.Print(string(kata[i])). You do not want to create a new local variable, instead modify the existing variable.
Here is the fixed code:
package main
import "fmt"
func main() {
var kata, kosong, kebalikan string
fmt.Print("Kata :")
fmt.Scan(&kata)
panjang := len(kata)
for i := panjang - 1; i >= 0; i-- {
kebalikan = kosong + fmt.Sprint(string(kata[i]))
}
if kata == kebalikan {
fmt.Println("\n", true)
} else {
fmt.Println("\n", false)
}
}

Check all data keys in golang at once

I have the following code:
type DisplayObject struct {
ID string `json:"id,omitempty" bson:"id"`
URI string `json:"uri,omitempty" bson:"uri"`
Display string `json:"display,omitempty" bson:"display"`
}
if DisplayObject.ID != "" {
// do something
}
if DisplayObject.URI != "" {
// do something
}
if DisplayObject.Display != "" {
// do something
}
In javascript I would do
for (var key in DisplayObject) {
if (DisplayObject.hasOwnProperty(key)) {
// do something
}
}
How can I accomplish this for loop through an object in go?
You could use reflection to accomplish something like that:
package main
import (
"fmt"
"reflect"
)
type DisplayObject struct {
ID string `json:"id,omitempty" bson:"id"`
URI string `json:"uri,omitempty" bson:"uri"`
Display string `json:"display,omitempty" bson:"display"`
}
func main() {
displayObj := &DisplayObject{ID: "foo"}
s := reflect.ValueOf(displayObj).Elem()
for i := 0; i < s.NumField(); i++ {
fieldName := s.Type().Field(i).Name
fieldValue := s.Field(i).String()
fmt.Printf("%s: %s\n", fieldName, fieldValue)
// do something with the field data
}
}
You are trying compare uncomparable. Javascript object is similar to map[string]interface{} . In your case could also be map[string]string and for maps you can use len(m) == 0.
Struct is much faster container, but less flexible container. You cannot change number or types of members.

Why the map doesn't return its value?

I have a function which simply returns the value of a map. However for some reasons it doesn't do that.
Any idea why ? I've pasted here the code. You may also play it using
Try it!
package main
import "fmt"
func main() {
a := CountryCode("Australia")
fmt.Println(a)
}
func CountryCode(s string) string {
m := make(map[string]string)
// [snip]
m["AU"] = "Australia"
// [snip]
return m[s]
}
func CodeByCountry(s string) string {
m := make(map[string]string)
// [snip]
m["Australia"] = "AU"
// [snip]
return m[s]
}
You're not using the right function, the one using the map whose key is a name. You probably want
a := CodeByCountry("Australia")
This works.
But it makes no sense to create the map each time you need it. Take the map creation out of the functions, and put it for example in the init :
package main
import "fmt"
var byCode = make(map[string]string)
var byName = make(map[string]string)
func init() {
m := byCode
m["AF"] = "Afghanistan"
m["AL"] = "Albania"
m["DZ"] = "Algeria"
m["AS"] = "American Samoa"
m = byName
m["Austria"] = "AT"
m["Mozambique"] = "MZ"
m["Solomon Islands"] = "SB"
m["United States"] = "US"
m["Anguilla"] = "AI"
m["Australia"] = "AU"
}
func CountryCode(s string) string {
return byCode[s]
}
func CodeByCountry(s string) string {
return byName[s]
}
func main() {
a := CodeByCountry("Australia")
fmt.Println(a)
}
Another solution for the initialization, as it seems bijective, would be to have one function adding a pair and filling both maps :
func addInMaps(code,name string) {
byCode[code] = name
byName[name] = code
}

Resources