如何动态清除类型结构的实例的值


是否可以

使用 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()))
}

(如果您传入非指针值,这将引起恐慌(

尽管这个问题是在 3 年零 9 个月前首次提出的,但 IMO 仍然没有一个好的答案,所以让我提出一个。

无需

反射,也无需在每次要清除变量时创建新实例。而是创建一个原始的新实例,将其保留在其初始清零状态,然后可以在要Reset()对象时将其复制到对象的内存中。(帽子提示@DaveC指出Reset()方法更惯用。

您只需使用指针从零值复制到对象指向的位置。以下内容为"将zeroA引用的内存值复制到a引用的内存位置

*a = *zeroA

这是我的完整示例,您也可以在Go Playground中尝试。(请注意,由于 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{}

游乐场链接:https://play.golang.org/p/Rf1BqfFe3IQ

可以使用结构的空对象重新分配值,这将重置值。

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

最新更新