如何将 nil 接口转换为 nil 其他接口
Posted
技术标签:
【中文标题】如何将 nil 接口转换为 nil 其他接口【英文标题】:How to cast nil interface to nil other interface 【发布时间】:2020-01-06 21:56:44 【问题描述】:我有一个经典的 Go nil 界面问题。
我正在尝试将我从nil
error
分配的interface
断言回error
接口。这句话令人困惑,所以我有一个方便的例子:https://play.golang.com/p/Qhv7197oIE_z
package main
import (
"fmt"
)
func preferredWay(i interface) error
return i.(error)
func workAround(i interface) error
if i == nil
return nil
return i.(error)
func main()
var nilErr error
fmt.Println(workAround(nilErr)) // Prints "<nil>" as expected.
fmt.Println(preferredWay(nilErr)) // Panics.
输出:
<nil>
panic: interface conversion: interface is nil, not error
goroutine 1 [running]:
main.preferredWay(...)
/tmp/sandbox415300914/prog.go:8
main.main()
/tmp/sandbox415300914/prog.go:21 +0xa0
换句话说,我试图从nil
interface
向下转换为nil
error
接口。如果我知道 interface
被分配为 nil
error
开始,是否有一种优雅的方法可以做到这一点?
仅供参考,如果这看起来不寻常,那是因为我正在实施一些模拟测试。
【问题讨论】:
无论值是否为nil
,在执行type assertion 时,请使用逗号-ok 习惯用法以避免出现恐慌。 (参见文档链接部分的最后一段)
考虑到我的用例,我不介意恐慌。我将它用于模拟客户端,因此在实施测试时,我可以为模拟客户端方法设置返回值。在这种情况下,恐慌实际上是有帮助的,因为恐慌很快就会失败,这意味着我的测试实施不正确。
【参考方案1】:
这行得通吗?
func preferredWay(i interface) error
k, _ := i.(error)
return k
【讨论】:
在这种情况下似乎是一个好方法。不过,我很好奇 nil 接口上类型断言的语义。甚至var i interface; i.(interface)
都惊慌失措。
在这种情况下,i 是 nil,所以类型断言恐慌,因为它查看接口的值,但值是 nil。 v,_:=i.(interface) 不会恐慌,因为 if 首先检查 i 是否可以转换为接口。如果 i 是具有 nil 值的非 nil 接口,则类型断言不会失败。
@ScottCrunkleton 这和nil
这个值关系不大,问题是nil
是untyped的,即"的类型存储在i
中的非值”不是interface
,不是任何东西,所以i.(interface)
失败,没有, ok
它会恐慌。尝试给i
一个typed nil
,然后断言i
给那个类型,它仍然恐慌吗?不,它没有。 play.golang.com/p/_xFk0jX5YIW
一个接口有一对引用,一个类型的引用和一个值的引用。如果接口本身是 nil,那么这些都是 nil。如果接口指向一个 nil 值,那么类型是非 nil(它指向 nil 值的类型),但值是 nil。如果接口是第一类,类型断言失败,因为类型为 nil。如果接口是第二种类型,则类型断言有效,因为存在非 nil 类型。
@bserdar +1 你的解释比我的尝试更准确、更清晰。以上是关于如何将 nil 接口转换为 nil 其他接口的主要内容,如果未能解决你的问题,请参考以下文章