当前位置: 首页 > 知识库问答 >
问题:

检查Go中的nil和nil接口

简嘉赐
2023-03-14

目前我正在使用这个帮助函数来检查nil和nil接口

func isNil(a interface{}) bool {
  defer func() { recover() }()
  return a == nil || reflect.ValueOf(a).IsNil()
}

因为<代码>反映。(a)的值。如果值的种类不是< code>Chan、< code>Func、< code>Map、< code>Ptr、< code>Interface或< code>Slice,IsNil()会出现混乱,我在deferred recover()中抛出了这些内容。

有没有更好的方法来实现这种检查?它认为应该有一个更直接的方法来做到这一点。

共有3个答案

宗啸
2023-03-14

不使用反射的两种解决方案:

将代码复制并粘贴到编辑器中:https://play.golang.org/查看实际操作。

以下代码:

一一一一一一一一一一一一一一一一一一一一

示例 #1:IsInterfaceNil()

一一一一一一一一一一一一一一一一一一一一

//:Example #1:
//:I prefer this method because the 
//:TakesInterface function does NOT need to know
//:about all the different implementations of
//:the interface.
package main;
import "fmt";

func main()(){

    var OBJ_OK *MyStruct = &( MyStruct{} );
    var NOT_OK *MyStruct = nil;
    
    //:Will succeed:
    TakesInterface( OBJ_OK );
    
    //:Will fail:
    TakesInterface( NOT_OK );

}

func TakesInterface( input_arg MyInterface ){

    if( input_arg.IsInterfaceNil() ){
        panic("[InputtedInterfaceIsNil]");
    }
    
    input_arg.DoThing();
}

type MyInterface interface{
    DoThing()()
    IsInterfaceNil()(bool)
}
type MyStruct struct{}
func(f *MyStruct)DoThing()(){
    fmt.Println("[MyStruct.DoThing]");
}
func(f *MyStruct)IsInterfaceNil()(bool){
    if(nil==f){ return true; }
    return false;
}

一一一一一一一一一一一一一一一一一一一一

示例#2:类型开关

一一一一一一一一一一一一一一一一一一一一

//:Example #2:
//:This will also work, but the function taking
//:the interface needs to know about all 
//:implementations. This defeats a bit of the
//:decoupling from implementation that an
//:interface offers, but if you are just using
//:interfaces for polymorphism, it's probably
//:an okay way to go. (opinion)
package main;
import "fmt";

func main()(){

    //:Will succeed:
    var OBJ_OK *IMPLMENTS_INTERFACE_01 = 
             &( IMPLMENTS_INTERFACE_01{} );
    TakesInterface( OBJ_OK );
    
    //:Will fail:
    var NOT_OK *IMPLMENTS_INTERFACE_01 = nil;
    TakesInterface( NOT_OK );
}

func TakesInterface( hasDoThing MyInterface ){

    //:THIS WILL NOT WORK:
    if(nil==hasDoThing){
        panic("[This_Error_Message_Will_Never_Happen]");
    }
    
    //:TYPE SWITCH TO THE RESCUE:
    switch v := hasDoThing.(type){
    
        case (*IMPLMENTS_INTERFACE_01): 
        if(nil==v){ panic("[Nil_PTR_01]"); }
        
        case (*IMPLMENTS_INTERFACE_02): 
        if(nil==v){ panic("[Nil_PTR_02]"); }
        
        case (*IMPLMENTS_INTERFACE_03): 
        if(nil==v){ panic("[Nil_PTR_03]"); }
        
        default: 
            panic("[UnsupportedInterface]");
    }
    
    hasDoThing.DoThing();
    
}

type IMPLMENTS_INTERFACE_01 struct{};
type IMPLMENTS_INTERFACE_02 struct{};
type IMPLMENTS_INTERFACE_03 struct{};
func (f *IMPLMENTS_INTERFACE_01)DoThing()(){
    fmt.Println( "DoingTheThing_01" );
}
func (f *IMPLMENTS_INTERFACE_02)DoThing()(){
    fmt.Println( "DoingTheThing_02" );
}
func (f *IMPLMENTS_INTERFACE_03)DoThing()(){
    fmt.Println( "DoingTheThing_03" );
}

type MyInterface interface{
    DoThing()()
}

更新:在我的代码库中实现后,我发现#2(类型开关)是最好的解决方案。特别是因为我不想编辑glfw。我正在使用的绑定库中的窗口结构。这是我的用例的粘贴箱。为我的非标准编码风格道歉。https://pastebin.com/22SUDeGG

锺离浩慨
2023-03-14

如果前面的两个选项都不适合你,到目前为止我能想到的最好的选择是:

if c == nil || (reflect.ValueOf(c).Kind() == reflect.Ptr && reflect.ValueOf(c).IsNil())

至少它可以检测到(*T)(无)案例。

公羊子真
2023-03-14

例如,在golang-nuts邮件列表中查看Kyle在此线程中的答案。

简而言之:如果你从来没有在一个接口中存储< code>(*T)(nil),那么你可以可靠地使用对nil的比较,不需要使用反射。另一方面,将无类型nil赋给一个接口总是可以的。

 类似资料:
  • 问题内容: 目前,我正在使用此辅助函数来检查nil和nil接口 由于恐慌,如果该值的种类比其他任何东西,,,,或者,我在推迟扔赶上那些。 有没有更好的方法来完成此检查?它认为应该有更直接的方法来做到这一点。 问题答案: 例如,在golang-nuts邮件列表中,请参阅此线程中的Kyle答案。 简而言之:如果您从不存储在接口中,那么您可以可靠地使用对nil的比较,而无需使用反射。另一方面,将无类型的

  • nil 和 BOOL 检查 类似于 Yoda 表达式,nil 检查的方式也是存在争议的。一些 notous 库像这样检查对象是否为 nil: if (nil == myValue) { ... 或许有人会提出这是错的,因为在 nil 作为一个常量的情况下,这样做就像 Yoda 表达式了。 但是一些程序员这么做的原因是为了避免调试的困难,看下面的代码: if (myValue == nil) { .

  • 本文向大家介绍总结IOS中nil、Nil、NULL和NSNull区别,包括了总结IOS中nil、Nil、NULL和NSNull区别的使用技巧和注意事项,需要的朋友参考一下 NULL 对于学习过 C/C++ 语言的朋友,对 NULL 一定很熟悉吧?这就是在 C/C++ 中的空指针。 在 C 语言中, NULL 是无类型的,只是一个宏,它代表空。我们不研究 C++ 中的 NULL ,因为在 C++11

  • 本文向大家介绍iOS中nil、Nil、NULL、NSNull详解,包括了iOS中nil、Nil、NULL、NSNull详解的使用技巧和注意事项,需要的朋友参考一下 ObjC 里面的几个空值符号经常会差点把我搞死,这些基础的东西一点要弄清楚才行,以提高码农的基本素质。 nil nil 是 ObjC 对象的字面空值,对应 id 类型的对象,或者使用 @interface 声明的 ObjC 对象。 例如

  • 问题内容: 我是Go编程的新手。我已经阅读了Go编程书籍,其中的内容由三部分组成:指向数组的指针,长度和容量。 我对nil slices(切片没有指向len的下层数组,len = 0,cap = 0),非lens切片(其中只有len = 0,cap = 0)和空切片之间感到困惑。 谁能告诉我nil和空片是否相同?如果两者都不相同,那么请说出两者之间的区别是什么? 如何测试切片是否为空? 另外,指针

  • 我是一个编程新手。我在go编程书中读到过,片由三部分组成:指向数组的指针、长度和容量。 我感到困惑的零切片(切片没有底层数组指向,len=0,cap=0),非零切片只有len=0,cap=0和空切片。 谁能告诉我零和空切片是否是一回事?如果它们都不同,那么请告诉这两者之间的区别是什么? 如何测试一个切片是否为空? 另外,指针在长度和容量为零的非nil片中保留什么值?