Assign pointer to variable in Golang - go

I am working in Golang, I have a Struct that contains some fields, one of them is a time.Time field to save the Delete_Atso it can be null, basically I have defined it as:
type Contact struct {
Delete_At *time.Time
}
So, with the pointer it can be null. Then, I have a method when this value is assigned, I have something like:
contact := Contact{}
contact.Deleted_At = time.Now()
But with it, I get:
cannot use time.Now() (type time.Time) as type *time.Time in assignment
I totally understand that is a bad assignment, but, how should I do it? how the conversion should be done?

t := time.Now()
contact.Deleted_At = &t
And BTW, you should not use _ in variable names. DeletedAt would be the recommended name.

Related

go when to use & or not?

I am confused whether to use a & with go when declaring a variable and init with a struct
say we have a struct wrapper
type HttpResult struct {
Status int32 `json:"status"`
Msg string `json:"msg"`
Data interface{} `json:"data,omitempty"`
}
and a struct defining the user model
type OmUser struct {
Id primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Name string `json:"name"`
Password string `json:"password"`
Email string `json:"email"`
}
And the following declaring seems give the same result:
myOmUser := OmUser{ //note no & sign here
Name: "Tony",
Password: "mypass",
Email: "tony#foo.com"
}
httpResult := &HttpResult{
Status: 0,
Msg: "ok",
Data: myOmUser,
}
js, _ := json.Marshal(httpResult)
fmt.Println(js)
Or
myOmUser := &OmUser{ //note the & sign
Name: "Tony",
Password: "mypass",
Email: "tony#foo.com"
}
httpResult := &HttpResult{
Status: 0,
Msg: "ok",
Data: myOmUser,
}
js, _ := json.Marshal(httpResult)
fmt.Println(js)
so, when to use & and why?
In your particular example it doesn't make a difference.
But when we look at an example of using json.Unmarshal() it makes a bit more sense:
jsonBlob := []byte(`{"id": "1", "name": "bob", "password": "pass", "email", "hi#me.com"}`)
var newOmUser OmUser
err := json.Unmarshal(jsonBlob, &newOmUser)
if err != nil {
panic(err)
}
Here we declare the variable before hand, and then we use the & to pass a pointer to that variable into the Unmarshal function.
That means that the Unmarshal function can reach out and update that variable, even though it's declared outside of the function.
Without the &, the Unmarshal function would get a copy of the newOmUser variable, and it would leave the original newOmUser variable that we declared empty.
When it comes to pointers, my general rule of thumb is:
Don't use them unless you have to.
If you need to use any unmarshalling functions, you'll need them. There are lots of other functions that make use of them.
Here's a quick exercise that helps me understand a little more about pointers:
func uppercase(s string) {
s = strings.ToUpper(s)
fmt.Println(s)
}
// Same as the uppercase() function, but works with a pointer.
func uppercasePointer(s *string) {
*s = strings.ToUpper(*s)
fmt.Println(*s)
}
name := "bob"
uppercase(name) // prints 'BOB'
fmt.Println(name) // prints 'bob' - our variable was not changed
name2 := "bobpointer"
uppercasePointer(&name2) // prints 'BOBPOINTER'
fmt.Println(name2) // prints 'BOBPOINTER' - our variable was changed
When we call the uppercase(name) function, go makes a copy of the name variable and sends it to the uppercase function.
Whatever the function does to that copy that it received stays in the function. The original variable that we declared outside the function is not changed.
When we call the uppercasePointer(&name2) function, we are sending a pointer to the name2 variable we declared.
The function can use that pointer to reach out and update the name2 variable that we declared earlier.
At first, you might not see the point of pointers, but as you continue to use go, you will see that they help us solve some complex problems.
Empty interface type in Go can hold values of any type. Tour here.
So in your HttpResult.Data is an empty interface type. So you can assigne any type to it.
The difference between defining a variable with & is getting a pointer of that type. Tour here.
Those are obviously two types with two different functionalities in Go. But you can assign both to empty interface type variable because its accepting values of any type.
package main
import (
"fmt"
"reflect"
)
type OmUser struct {
}
func main() {
myOmUser := OmUser{}
myOmUser2 := &OmUser{}
fmt.Println(reflect.TypeOf(myOmUser)) //main.OmUser
fmt.Println(reflect.TypeOf(myOmUser2)) //*main.OmUser
}
For more details about &, read Go doc address operators
For an
operand x of type T, the address operation &x generates a pointer of
type *T to x. The operand must be addressable, that is, either a
variable, pointer indirection, or slice indexing operation; or a field
selector of an addressable struct operand; or an array indexing
operation of an addressable array. As an exception to the
addressability requirement, x may also be a (possibly parenthesized)
composite literal. If the evaluation of x would cause a run-time
panic, then the evaluation of &x does too.
fooA := &Foo{}
fooA has type *Foo.
fooB := Foo{}
fooB has type Foo.
https://tour.golang.org/moretypes/1
In practice, this means if you had a func that accepted type *Foo you could do either of the following...
func someFunc(f *Foo) {
// ...
}
fooA := &Foo{}
someFunc(fooA)
fooB := Foo{}
someFunc(&fooB)
So realistically, create whichever you need to be honest.

How to store current time for struct's field of type *time.Time in DataStore? [duplicate]

This question already has an answer here:
Assign value returned from function to pointer
(1 answer)
Closed 3 years ago.
According to my requirements, I created one struct as -
type MyRule struct {
CreatedAt time.Time `json:"createdAt" datastore:"createdAt,noindex"`
UpdatedAt *time.Time `json:"updatedAt" datastore:"updatedAt,noindex"`
}
for createdAt field, I am able to store current time as-
MyRule.CreatedAt = time.Now()
However, the same thing does not work to store current time in updatedAt field of MyRule struct as it's type is *time.Time and not time.Time.
Here, I can't change field type of updatedAt because *time.Time allows me to accept nil as updatedAt value when I create any rule.
If I try to do this as-
MyRule.UpdatedAt = time.Now()
It gives me below error-
cannot use time.Now()(type time.Time) as type *time.Time in assignment
How can I store current time value in updatedAt field of type *time.Time and not time.Time
Note: one cannot get the address of a return value, so something like this will NOT work:
MyRule.UpdatedAt = &time.Now() // compile fail
To get the address of a value, it must be in an addressable item. So assign the value to a variable, like so:
t := time.Now()
MyRule.UpdatedAt = &t

golang: reflect.ValueOf(x).Type() always equals to reflect.TypeOf(x)? [duplicate]

I'm not very clear about what this code snippet behaves.
func show(i interface{}) {
switch t := i.(type) {
case *Person:
t := reflect.TypeOf(i) //what t contains?
v := reflect.ValueOf(i) //what v contains?
tag := t.Elem().Field(0).Tag
name := v.Elem().Field(0).String()
}
}
What is the difference between the type and value in reflection?
reflect.TypeOf() returns a reflect.Type and reflect.ValueOf() returns a reflect.Value. A reflect.Type allows you to query information that is tied to all variables with the same type while reflect.Value allows you to query information and preform operations on data of an arbitrary type.
Also reflect.ValueOf(i).Type() is equivalent to reflect.TypeOf(i).
In the example above, you are using the reflect.Type to get the "tag" of the first field in the Person struct. You start out with the Type for *Person. To get the type information of Person, you used t.Elem(). Then you pulled the tag information about the first field using .Field(0).Tag. The actual value you passed, i, does not matter because the Tag of the first field is part of the type.
You used reflect.Value to get a string representation of the first field of the value i. First you used v.Elem() to get a Value for the struct pointed to by i, then accessed the first Field's data (.Field(0)), and finally turned that data into a string (.String()).

Generic Programming in Go, Implicit generic type

I need Go to implicitly resolve my struct type, in order to do generic replacement of some attribute.
//must replace the attribute with attValue
func SetAttribute(object interface{}, attributeName string, attValue interface{}, objectType reflect.Type) interface{} {
/// works perfectly, but function SetAttribute needs to know Customer type to do the convertion
convertedObject := object.(Customer) // <-- Need to hard code a cast :(
// doesn't works... raise panic!
//convertedObject := object
value := reflect.ValueOf(&convertedObject).Elem()
field := value.FieldByName(attributeName)
valueForAtt := reflect.ValueOf(attValue)
field.Set(valueForAtt)
return value.Interface()
}
Please check out full example in the Go playground...
http://play.golang.org/p/jxxSB5FKEy
convertedObject is the value of what is in the object interface. Taking the address of that has no effect on the original customer. (and converted is probably a poor prefix for the name, since that is generated from a "type assertion", not a "type conversion")
If you use object directly, it panics, because you're then taking the address of the interface, not the customer.
You need to pass the address of the customer you want to modify to the function:
SetAttribute(&customer, "Local", addressNew, reflect.TypeOf(Customer{}))
You can also have your SetAttribute check if it's a pointer first:
if reflect.ValueOf(object).Kind() != reflect.Ptr {
panic("need a pointer")
}
value := reflect.ValueOf(object).Elem()
field := value.FieldByName(attributeName)
valueForAtt := reflect.ValueOf(attValue)
field.Set(valueForAtt)
return value.Interface()

Set a pointer to a field using reflection

i have the following struct, and need some of the fields to be nulluble so i use pointers, mainly to handle sql nulls
type Chicken struct{
Id int //Not nullable
Name *string //can be null
AvgMonthlyEggs *float32 //can be null
BirthDate *time.Time //can be null
}
so when i do the following i can see that the json result can have nulls for value types which is what i want
stringValue:="xx"
chicken := &Chicken{1,&stringValue,nil,nil}
chickenJson,_ := json.Marshal(&chicken)
fmt.Println(string(chickenJson))
but when i try to do it all using reflection
var chickenPtr *Chicken
itemTyp := reflect.TypeOf(chickenPtr).Elem()
item := reflect.New(itemTyp)
item.Elem().FieldByName("Id").SetInt(1)
//the problem is here not sure how to set the pointer to the field
item.Elem().FieldByName("Name").Set(&stringValue) //Error caused by this line
itemJson,_ := json.Marshal(item.Interface())
fmt.Println(string(itemJson))
what i get from the reflection part is the following error
cannot use &stringValue (type *string) as type reflect.Value in argument to item.Elem().FieldByName("Name").Set
what am i doing wrong?
here is a GoPlay http://play.golang.org/p/0xt45uHoUn
reflect.Value.Set only accepts reflect.Value as an argument. Use reflect.ValueOf on your stringValue:
item.Elem().FieldByName("Name").Set(reflect.ValueOf(&stringValue))
Playground: http://play.golang.org/p/DNxsbCsKZA.

Resources