Check for nil and nil interface in Go
Solution 1:
See for example Kyle's answer in this thread at the golang-nuts mailing list.
In short: If you never store (*T)(nil)
in an interface, then you can reliably use comparison against nil, no need to use reflection. On the other hand, assigning untyped nil to an interface is always OK.
Solution 2:
If neither of the earlier options works for you, the best I could came up so far is:
if c == nil || (reflect.ValueOf(c).Kind() == reflect.Ptr && reflect.ValueOf(c).IsNil())
At least it detects (*T)(nil) cases.
Solution 3:
Two solutions NOT using reflection:
Copy and paste code into editor at: https://play.golang.org/ to see in action.
1: Add an "IsInterfaceNil()" function to interface.
2: Use A "type switch"
CODE BELOW:
一一一一一一一一一一一一一一一一一一一一
EXAMPLE #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;
}
一一一一一一一一一一一一一一一一一一一一
EXAMPLE #2: Type Switch
一一一一一一一一一一一一一一一一一一一一
//: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()()
}
UPDATE: After implementing in my code base, I found #2 (type switch) to be best solution. Specifically because I DON'T want to EDIT the glfw.Window struct in the bindings library I am using. Here is a paste-bin of my use-case. Apologies for my non-standard coding style. https://pastebin.com/22SUDeGG