如何动态清除类型结构实例的值
How to clear values of a instance of a type struct dynamically
是否可以使用 Go 创建一个动态清除结构实例值的方法?
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
}
如果不传递指向原始值的指针,则无法修改它们。
在您的代码中简单地分配一个新的零值会更容易、更清晰。如果你的类型更复杂,你可以用构造函数替换值,或者为你的类型提供 Reset()
方法和指针接收器。
如果你真的想看看如何通过反射来实现它,你的 clear
函数可能如下所示:http://play.golang.org/p/g0zIzQA06b
func clear(v interface{}) {
p := reflect.ValueOf(v).Elem()
p.Set(reflect.Zero(p.Type()))
}
(如果你传入一个非指针值,这会造成恐慌)
可以使用将重置值的结构的空对象重新分配值。
a := A{"Momo", 1}
b := B{"Starfall"}
fmt.Println(a)
fmt.Println(b)
// outputs
// {"Momo", 1}
// {"Starfall"}
a = A{}
b = B{}
// outputs
// { , 0}
// { }
尽管这个问题是在 3 年零 9 个月前首次提出的,但 IMO 仍然没有一个好的答案,所以让我提出一个。
不需要反射,也不需要每次要清除变量时都创建一个新实例。相反,创建一个原始的新实例,您将其保留在其初始归零状态,然后您可以在需要 Reset()
时复制对象的内存。 (向@DaveC 致敬,指出 Reset()
方法更为惯用。)
您只需使用指针从归零值复制到对象指向的位置。下面写"Copy the value of the memory that zeroA
references to the memory location that a
references.":
*a = *zeroA
这是我的完整示例,您也可以在 the Go Playground. (Note that since your receiver 中尝试,因为 Reset()
是指向类型 A
的指针,然后调用 Reset()
方法允许您更新a
的值,其中更新在方法调用结束后仍然存在):
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)
}
这是你的输出 (请注意,我证明你的变量已清零,指向该变量的指针也已清零,但如果你制作了原始文件的*副本*,则不会归零):
{Momo 1}
&{Momo 1}
{Momo 1}
{ 0}
&{ 0}
{Momo 1}
您还可以使用此技术复制包含默认值的结构的值。 但是请注意,这是一个浅拷贝,而不是深拷贝。如果您的 struct
包含任何指针属性,此方法也会复制指针值,并且不会分配内存以指向所指向值的新副本。因此,如果您想将结构重置为新的默认值,包括使用指针声明的任何子结构的副本,您将需要在 Reset()
中做额外的工作。
我希望这对其他人有帮助,这样他们就不必像我一样费力地学习它。
您可以像这样将它设置为空结构:
var obj myStruct
obj.field1 = "apple"
obj.field2 = 12
// Reset struct.
obj = myStruct{}
是否可以使用 Go 创建一个动态清除结构实例值的方法?
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
}
如果不传递指向原始值的指针,则无法修改它们。
在您的代码中简单地分配一个新的零值会更容易、更清晰。如果你的类型更复杂,你可以用构造函数替换值,或者为你的类型提供 Reset()
方法和指针接收器。
如果你真的想看看如何通过反射来实现它,你的 clear
函数可能如下所示:http://play.golang.org/p/g0zIzQA06b
func clear(v interface{}) {
p := reflect.ValueOf(v).Elem()
p.Set(reflect.Zero(p.Type()))
}
(如果你传入一个非指针值,这会造成恐慌)
可以使用将重置值的结构的空对象重新分配值。
a := A{"Momo", 1}
b := B{"Starfall"}
fmt.Println(a)
fmt.Println(b)
// outputs
// {"Momo", 1}
// {"Starfall"}
a = A{}
b = B{}
// outputs
// { , 0}
// { }
尽管这个问题是在 3 年零 9 个月前首次提出的,但 IMO 仍然没有一个好的答案,所以让我提出一个。
不需要反射,也不需要每次要清除变量时都创建一个新实例。相反,创建一个原始的新实例,您将其保留在其初始归零状态,然后您可以在需要 Reset()
时复制对象的内存。 (向@DaveC 致敬,指出 Reset()
方法更为惯用。)
您只需使用指针从归零值复制到对象指向的位置。下面写"Copy the value of the memory that zeroA
references to the memory location that a
references.":
*a = *zeroA
这是我的完整示例,您也可以在 the Go Playground. (Note that since your receiver 中尝试,因为 Reset()
是指向类型 A
的指针,然后调用 Reset()
方法允许您更新a
的值,其中更新在方法调用结束后仍然存在):
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)
}
这是你的输出 (请注意,我证明你的变量已清零,指向该变量的指针也已清零,但如果你制作了原始文件的*副本*,则不会归零):
{Momo 1}
&{Momo 1}
{Momo 1}
{ 0}
&{ 0}
{Momo 1}
您还可以使用此技术复制包含默认值的结构的值。 但是请注意,这是一个浅拷贝,而不是深拷贝。如果您的 struct
包含任何指针属性,此方法也会复制指针值,并且不会分配内存以指向所指向值的新副本。因此,如果您想将结构重置为新的默认值,包括使用指针声明的任何子结构的副本,您将需要在 Reset()
中做额外的工作。
我希望这对其他人有帮助,这样他们就不必像我一样费力地学习它。
您可以像这样将它设置为空结构:
var obj myStruct
obj.field1 = "apple"
obj.field2 = 12
// Reset struct.
obj = myStruct{}