繁体   English   中英

在Golang中将接口设置为nil

[英]Set an interface to nil in Golang

我正在尝试将接口的内部值设置为nil ,如下所示:

typ := &TYP{InternalState: "filled"}
setNil(typ)

fmt.Printf("Expecting that %v to be nil", typ)

我需要知道如何实现setNil(typ interface{})方法。

有关更多详细信息, 请参阅play.golang.org中的此代码

问题是你没有接口值。 你有一个指针值,一个指向具体类型的指针。 这与界面值不同。

如果要更改任何类型的变量的值,则必须将指针传递给它。 这还包括接口类型的变量,以及指针类型的变量。 interface{}的指针有意义时( *interface{} ),这是非常罕见的情况之一,实际上它是不可避免的。

但是,如果您的函数需要一个接口并且您传递了一个非接口值,那么将隐式创建一个接口值,您只能nil这个隐式创建的值。

所以我们有2个不同/不同的案例:

nil interface{}函数interface{}

func setNilIf(v *interface{}) {
    *v = nil
}

使用它:

var i interface{} = "Bob"
fmt.Printf("Before: %v\n", i)
setNilIf(&i)
fmt.Printf("After: %v\n", i)

输出:

Before: Bob
After: <nil>

所以它有效。

nil指针的函数; 使用unsafe

其实这是你的情况。 我们想要改变指针类型变量的值。 要接受指向任何类型的指针,我们可以使用unsafe.Pointer unsafe.Pointer是一种语言支持 ,它是一种特殊的指针类型,可以从任何指针类型转换。

我们想接受指针变量的地址(指针),类似于**SomeType 为了能够为指针变量分配新值( nil ),我们必须取消引用它( *运算符)。 但是unsafe.Pointer不能被解除引用,所以首先我们必须将它转换为指向“某事”的指针,但是因为我们只想指定nil (这与所有指针类型相同,而不管指向值的类型如何),“东西”没关系,我只会使用int ,所以我将unsafe.Pointer指针值转换为**int

func setNilPtr(p unsafe.Pointer) {
    *(**int)(p) = nil
}

使用它:

typ := &TYP{InternalState: "filled"}
fmt.Printf("Before: %v\n", typ)
setNilPtr(unsafe.Pointer(&typ))
fmt.Printf("After: %v\n", typ)

输出:

Before: &{filled}
After: <nil>

所以这一个也有效。 还有另一种使用反射的方法:

nil指针的函数; 使用reflect

您也可以nil一个使用指针只反射( reflect包)。 我们仍然需要传递指针类型变量的地址。 请注意,在这种情况下,参数的类型将只是interface{} 它将包含一个动态类型,如**SomeType 由于指针的值nil ,我们可以使用reflect.Zero()获取这样的值,我们将使用Value.Set()来设置它:

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

使用它:

typ2 := &TYP{InternalState: "filled"}
fmt.Printf("Before: %v\n", typ2)
setNilPtr2(&typ2)
fmt.Printf("After: %v\n", typ2)

输出:

Before: &{filled}
After: <nil>

所以这一个也有效。 Go Playground尝试这些。


但严重的是:如果你想nil事,分配nil它。 不要不必要地使事情复杂化。

i = nil
typ = nil

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM