Go Secret — Interface{}: Let Me Tell You Another Thing

Go Secret — Interface{}: Let Me Tell You Another Thing

We will examine how it can hold values of any type, explore its internal structure and how it handles equality comparisons.

In this section, we will delve deeper into the interface{} type and gain a comprehensive understanding of how it operates.

Secret series:

Let’s dive in.

1. Interface actually holds 2 things, not one.

When a variable of a specific type is assigned to an interface{} variable, Go actually creates a new structure that contains both the type descriptor and the value of that variable.

This process is called “boxing” the value, you can imagine an interface{} like this:

type iface struct {
tab *itab
data unsafe.Pointer
}

The type descriptor tab is a small structure that contains information the interface’s method set, the underlying type, and the methods of the underlying type that implement the interface:

type itab struct {
inter *interfacetype
_type *_type
hash uint32 // copy of _type.hash. Used for type switches.
_ [4]byte
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}

The pointer to the value in an interface{} variable simply points to the memory location where the value is stored.

When an interface{} value is extracted, Go “unboxes” it by accessing the type descriptor and pointer, it then creates a new variable of the appropriate type using this information. This process is handled by the Go runtime.

“How did you come to know about these secrets?”

You can find more information by looking into the Go runtime repository, which contains a collection of functions and data structures that are utilized by the Go runtime system to manage the execution of Go programs.

2. Nil is not Nil

When an interface{} variable holds a nil value, it doesn’t necessarily mean it is equal to nil. Here’s an example to illustrate this:

func main() {
var x interface{}
var y *int = nil
x = y

if x != nil {
fmt.Println("x != nil") // actual
} else {
fmt.Println("x == nil") // expect
}

fmt.Println(x)
}

// x != nil
// <nil>

In this example, I assigned x to the nil pointer int value, but the actual result is “x != nil”, even though when I print the value of x, it also shows <nil>

This is because when comparing an interface{} variable to nil using the == operator, it will only return true if both the type descriptor and the value data are nil.

“So ridiculous, how can I fix this?”

I typically use reflection to resolve this issue since I don’t need to know the underlying type. I also write an utility function to check for nil values:

func IsAnyNil(x interface{}) bool {
return reflect.ValueOf(x).IsNil()
}

“So, interface(int64) = 1 and interface(int32) are not equal… correct?”

As we discussed earlier, you are correct that the value 1 in an interface{} of type int64 is not equal to the value 1 in an interface{} of type int32. To confirm this, I have run a test for you:

func main() {
var y int32 = 1
var z int64 = 1

var x1 interface{} = y
var x2 interface{} = z

if x1 == x2 {
fmt.Println("x1 == x2") // expect
} else {
fmt.Println("x1 != x2") // actual
}
}

// x1 != x2

That concludes our discussion. You now have a full understanding of how interface{} works and can use this knowledge with confidence.

Another Great Post Completed

If you’re interested in staying up to date with the latest happenings in the Software Engineering world, give me a follow. I’ll be sure to keep you in the loop!

Also, every 👏 helps to spread the word about my writing and I would really appreciate it.

Just remember to always keep learning and have fun with it, happy coding!

Level Up Coding

Thanks for being a part of our community! Before you go:

🚀👉 Join the Level Up talent collective and find an amazing job


Go Secret — Interface{}: Let Me Tell You Another Thing was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Aiden (func25)

Go Secret — Interface{}: Let Me Tell You Another Thing

We will examine how it can hold values of any type, explore its internal structure and how it handles equality comparisons.

In this section, we will delve deeper into the interface{} type and gain a comprehensive understanding of how it operates.

Secret series:

Let’s dive in.

1. Interface actually holds 2 things, not one.

When a variable of a specific type is assigned to an interface{} variable, Go actually creates a new structure that contains both the type descriptor and the value of that variable.

This process is called “boxing” the value, you can imagine an interface{} like this:

type iface struct {
tab *itab
data unsafe.Pointer
}

The type descriptor tab is a small structure that contains information the interface’s method set, the underlying type, and the methods of the underlying type that implement the interface:

type itab struct {
inter *interfacetype
_type *_type
hash uint32 // copy of _type.hash. Used for type switches.
_ [4]byte
fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}

The pointer to the value in an interface{} variable simply points to the memory location where the value is stored.

When an interface{} value is extracted, Go "unboxes" it by accessing the type descriptor and pointer, it then creates a new variable of the appropriate type using this information. This process is handled by the Go runtime.

“How did you come to know about these secrets?”

You can find more information by looking into the Go runtime repository, which contains a collection of functions and data structures that are utilized by the Go runtime system to manage the execution of Go programs.

2. Nil is not Nil

When an interface{} variable holds a nil value, it doesn't necessarily mean it is equal to nil. Here's an example to illustrate this:

func main() {
var x interface{}
var y *int = nil
x = y

if x != nil {
fmt.Println("x != nil") // actual
} else {
fmt.Println("x == nil") // expect
}

fmt.Println(x)
}

// x != nil
// <nil>

In this example, I assigned x to the nil pointer int value, but the actual result is “x != nil”, even though when I print the value of x, it also shows <nil>

This is because when comparing an interface{} variable to nil using the == operator, it will only return true if both the type descriptor and the value data are nil.

“So ridiculous, how can I fix this?”

I typically use reflection to resolve this issue since I don’t need to know the underlying type. I also write an utility function to check for nil values:

func IsAnyNil(x interface{}) bool {
return reflect.ValueOf(x).IsNil()
}
“So, interface(int64) = 1 and interface(int32) are not equal… correct?”

As we discussed earlier, you are correct that the value 1 in an interface{} of type int64 is not equal to the value 1 in an interface{} of type int32. To confirm this, I have run a test for you:

func main() {
var y int32 = 1
var z int64 = 1

var x1 interface{} = y
var x2 interface{} = z

if x1 == x2 {
fmt.Println("x1 == x2") // expect
} else {
fmt.Println("x1 != x2") // actual
}
}

// x1 != x2

That concludes our discussion. You now have a full understanding of how interface{} works and can use this knowledge with confidence.

Another Great Post Completed

If you’re interested in staying up to date with the latest happenings in the Software Engineering world, give me a follow. I’ll be sure to keep you in the loop!

Also, every 👏 helps to spread the word about my writing and I would really appreciate it.

Just remember to always keep learning and have fun with it, happy coding!

Level Up Coding

Thanks for being a part of our community! Before you go:

🚀👉 Join the Level Up talent collective and find an amazing job


Go Secret — Interface{}: Let Me Tell You Another Thing was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Aiden (func25)


Print Share Comment Cite Upload Translate Updates
APA

Aiden (func25) | Sciencx (2023-01-30T01:55:12+00:00) Go Secret — Interface{}: Let Me Tell You Another Thing. Retrieved from https://www.scien.cx/2023/01/30/go-secret-interface-let-me-tell-you-another-thing/

MLA
" » Go Secret — Interface{}: Let Me Tell You Another Thing." Aiden (func25) | Sciencx - Monday January 30, 2023, https://www.scien.cx/2023/01/30/go-secret-interface-let-me-tell-you-another-thing/
HARVARD
Aiden (func25) | Sciencx Monday January 30, 2023 » Go Secret — Interface{}: Let Me Tell You Another Thing., viewed ,<https://www.scien.cx/2023/01/30/go-secret-interface-let-me-tell-you-another-thing/>
VANCOUVER
Aiden (func25) | Sciencx - » Go Secret — Interface{}: Let Me Tell You Another Thing. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2023/01/30/go-secret-interface-let-me-tell-you-another-thing/
CHICAGO
" » Go Secret — Interface{}: Let Me Tell You Another Thing." Aiden (func25) | Sciencx - Accessed . https://www.scien.cx/2023/01/30/go-secret-interface-let-me-tell-you-another-thing/
IEEE
" » Go Secret — Interface{}: Let Me Tell You Another Thing." Aiden (func25) | Sciencx [Online]. Available: https://www.scien.cx/2023/01/30/go-secret-interface-let-me-tell-you-another-thing/. [Accessed: ]
rf:citation
» Go Secret — Interface{}: Let Me Tell You Another Thing | Aiden (func25) | Sciencx | https://www.scien.cx/2023/01/30/go-secret-interface-let-me-tell-you-another-thing/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.