Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clear values of a instance of a type struct dynamically

Tags:

struct

go

Is it possible with Go to make a method that dynamically clears the values of a instance of a struct?

type A struct {
    Name string
    Level int
}

type B struct {
    Skill string
}

func main() {
    a := A{"Momo", 1}
    b := B{"Starfall"}

    // outputs
    // {"Momo", 1}
    // {"Starfall"}

    clear(a)
    clear(b)

    // outputs
    // { , 0}
    // { }
}

func clear(v interface{}) {
    // some code
}
like image 712
kudarap Avatar asked Mar 20 '15 14:03

kudarap


4 Answers

You can't modify the original values without passing a pointer to them.

It's much easier and more clear to simply assign a new zero value in your code. If your types are more complex, you can replace the values with a constructor, or provide Reset() methods for your types with a pointer receiver.

If you really want to see how to do it via reflection your clear function could look like: http://play.golang.org/p/g0zIzQA06b

func clear(v interface{}) {
    p := reflect.ValueOf(v).Elem()
    p.Set(reflect.Zero(p.Type()))
}

(This will panic if you pass in a non-pointer value)

like image 165
JimB Avatar answered Nov 14 '22 02:11

JimB


Even though this question was first asked 3 years and 9 months ago it IMO still does not have a good answer so let me propose one.

There is no need for reflection, or to create a new instance each time you want to clear your variable. Instead create one pristine new instance that you leave in its initial zeroed state which you can then copy over your object's memory when you want to Reset() it. (Hat tip to @DaveC for pointing out that a Reset() method is more idiomatic.)

You simply copy from your zeroed value to the location at which your object points to using pointers. The following reads "Copy the value of the memory that zeroA references to the memory location that a references.":

*a = *zeroA

Here is my full example which you can also try in the Go Playground. (Note that since your receiver for Reset() is a pointer to type A then calling the Reset() method allows you to update the value of a where the update survives past the end of the method call):

package main

import (
    "fmt"
)

type A struct {
    Name string
    Level int
}
var zeroA = &A{}
func (a *A) Reset() {
    *a = *zeroA
}

func main() {
    a1 := A{"Momo", 1}
    a2 := &a1
    a3 := a1

    fmt.Println(a1)
    fmt.Println(a2)
    fmt.Println(a3)

    a1.Reset()

    fmt.Println(a1)
    fmt.Println(a2)
    fmt.Println(a3)
}

And here is your output (Note that I prove that your variable is zeroed out and a pointer to that variable is also zeroed, but if you made a *copy* of the original it is not zeroed):

{Momo 1}
&{Momo 1}
{Momo 1}
{ 0}
&{ 0}
{Momo 1}    

You can also use this technique to copy over the values of a struct that contains default values. However be aware that this is a shallow copy, not a deep copy. If your struct contains any properties that are pointers this approach will copy the pointer values over too and will not allocate memory to point to new copies of the values pointed to. So you will need to do extra work in Reset() if you want to reset your struct to new defaults, including copies of any sub-structs that are declared with pointers.

I hope this helps others so they do not have to learn this the hard way like it took me.

like image 31
MikeSchinkel Avatar answered Nov 14 '22 02:11

MikeSchinkel


You can just set it to an empty struct like so:

var obj myStruct
obj.field1 = "apple"
obj.field2 = 12

// Reset struct.
obj = myStruct{}

Playground link: https://play.golang.org/p/Rf1BqfFe3IQ

like image 30
Floating Sunfish Avatar answered Nov 14 '22 04:11

Floating Sunfish


It's possible to reassign the value with an empty object of the struct which will reset the values.

a := A{"Momo", 1}
b := B{"Starfall"}

fmt.Println(a)
fmt.Println(b)
// outputs
// {"Momo", 1}
// {"Starfall"}

a = A{}
b = B{}
// outputs
// { , 0}
// { }

https://play.golang.org/p/CJ6cx2TFytY

like image 35
AESTHETICS Avatar answered Nov 14 '22 04:11

AESTHETICS