Some code that will nil an interface's value while leaving its type intact.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"unsafe" | |
"github.com/google/uuid" | |
) | |
// NullInterfaceValue takes an interface ref, constructs an new struct from | |
// the pointer, allowing us to modify the parts of the pointer, and sets the | |
// interface's value to nil. | |
func NullInterfaceValue(x *interface{}) { | |
e := (*emptyInterface)(unsafe.Pointer(x)) | |
e.word = nil | |
} | |
func main() { | |
var uid interface{} = uuid.New() | |
NullInterfaceValue(&uid) | |
switch val := uid.(type) { | |
case nil: | |
fmt.Println("value is nil") | |
case fmt.Stringer: | |
fmt.Println(val.String()) | |
} | |
} | |
// Interfaces below are from the reflect package -- (c) Go Authors 2009/BSD. | |
// emptyInterface is the header for an interface{} value. | |
type emptyInterface struct { | |
typ *rtype | |
word unsafe.Pointer | |
} | |
type rtype struct { | |
size uintptr | |
ptrdata uintptr // number of bytes in the type that can contain pointers | |
hash uint32 // hash of type; avoids computation in hash tables | |
tflag tflag // extra type information flags | |
align uint8 // alignment of variable with this type | |
fieldAlign uint8 // alignment of struct field with this type | |
kind uint8 // enumeration for C | |
// function for comparing objects of this type | |
// (ptr to object A, ptr to object B) -> ==? | |
equal func(unsafe.Pointer, unsafe.Pointer) bool | |
gcdata *byte // garbage collection data | |
str nameOff // string form | |
ptrToThis typeOff // type for pointer to this type, may be zero | |
} | |
type tflag uint8 | |
type nameOff int32 // offset to a name | |
type typeOff int32 // offset to an *rtype |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I didn't see a way to comment on your blog post, so I'm posting this here, but you don't need to use the above to run into this situation. If you run the program below, you'll see some of the ways you can encounter this:
If you comment out the
IsNil()
reflection check, it willpanic
as expected.Also, this happens often enough with
error
(an interface) that it is mentioned in the FAQ: https://go.dev/doc/faq#nil_error.Nil receivers are by design as well, see: https://go.dev/tour/methods/12.