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
}
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)
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.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With