在Golang中将接口设置为nil



我正在尝试将接口的内部值设置为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这个隐式创建的值。

因此,我们有两种不同/不同的情况:

nilinterface{}的函数

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

使用它:

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

输出:

Before: Bob
After: <nil>

所以它是有效的。

函数为nil一个指针;使用unsafe

事实上这就是你的情况。我们想要更改指针类型的变量的值。要接受指向任何类型的指针,我们可以使用unsafe.Pointerunsafe.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: %vn", typ)
setNilPtr(unsafe.Pointer(&typ))
fmt.Printf("After: %vn", 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: %vn", typ2)
setNilPtr2(&typ2)
fmt.Printf("After: %vn", typ2)

输出:

Before: &{filled}
After: <nil>

所以这个也是有效的。在围棋场上试试这些。


但说真的:如果你想nil,就给它分配nil。不要让事情变得不必要的复杂。

i = nil
typ = nil

相关内容

  • 没有找到相关文章

最新更新