Behaviour of nil receiver in method in Golang - go

package main
import (
"fmt"
)
type I interface {
M()
}
type T struct {
}
func (t *T) M() {
fmt.Println(t == nil)
}
func main() {
var i I
var t *T
i = t
fmt.Println(i == nil)
i.M()
}
The result is false and true.
The value in both cases is nil and type is *main.T.
I understand that in the first case i == nil is false because the variable i does not have a nil type.
I do not understand why t == nil is true inside the method M().

In the first case, i==nil is false, because i is an interface whose type is T and whose value is nil. For an interface to be equal to the literal value nil, it has to have both type and value nil. Here, i has non-nil type.
In the second case, the receiver is simply nil, because the receiver of the function M is a value of type *T whose value is nil.

Related

Why type assertion of an interface equal to nil in type switch non-nil branch? [duplicate]

This question already has answers here:
Hiding nil values, understanding why Go fails here
(3 answers)
Closed 5 months ago.
Given the codes
type Int struct {
v int
}
func typeAssert(val any) {
switch v := val.(type) {
case nil:
fmt.Println("val type is nil")
case *Int:
fmt.Println("val type is *Int")
if v == nil {
fmt.Println("val after type assertion is nil?")
}
}
}
func main() {
var i1 *Int
typeAssert(i1)
}
Output:
val type is *Int
val after type assertion is nil?
What confuses me is that since the *Int is matched in switch v := val.(type), why could the v == nil be true? If the v == nil be true, the case nil could be matched, actually, it does not.
Because there are two kinds of nil with an interface value:
A nil interface, which would hit the first branch of your type switch. This is like var x interface{} = nil - not only is the value nil, the type is also nil.
A nil value, like var x interface = (nil)(*Int). This hits the second branch, because it has a type, the type matches the type in the switch, but the value is nil. In the code, v is a *Int whose value is nil.

Interfaces can be of type nil but that doesn't mean they are nil?

I wrote a bit of code that in effect does this:
package main
import "fmt"
type SomeInterface interface {
Retrieve(identifier string)
}
type SomeStruct struct {}
func (r SomeStruct) Retrieve(identifier string) {
fmt.Println("identifier ", identifier)
}
type Handler struct {
Name string
SomeObject SomeInterface
}
func main() {
var someStruct *SomeStruct
var h = Handler{
Name: "helo",
SomeObject: someStruct,
}
fmt.Printf("before %+v\r\n", h.SomeObject)
if h.SomeObject == nil {
fmt.Printf("during %+v\r\n", h.SomeObject)
}
fmt.Printf("after %+v\r\n", h.SomeObject)
}
Please can someone explain to me why the output of the above is:
before <nil>
after <nil>
I've been reading about interfaces of type nil but in this case I have assigned the interface to a pointer that hasn't been assigned so I would have thought that the interface == nil and I would see during <nil> - alas it is not the case.
An interface value is a simple data structure with two parts, a type and an underlying value. So, the interface value itself can be nil, or the interface value can exist but the underlying value can be nil. For example:
var x interface{} = nil // x is nil
var y interface{} = (interface{})(nil) // y is a interface{}, which *contains* nil
This is in some ways conceptually similar to this difference:
var x []*int = nil // x is nil
var y []*int = []*int{nil} // y is a []*int, which *contains* nil
fmt.Printf obscures the difference in the case of an interface because of the way it formats the output; you could see the difference more clearly using reflection if you wanted to.
SomeObject is not nil, it just points to SomeStruct which is nil.
i think the confusion is fmt.Printf prints <nil> for this case cuz it's following the pointer and that end result is nil.
In Go, a variable referring to an implementer of some interface can have many types. It can be of type <nil> (yes, nil can describe a type as well as a value), it can be the type of one of its implementers, or it can be the type of a pointer to one of its implementers. By default, a variable referring to an interface is of type nil. Once you've assigned something to it (other than nil itself), it will then take on the type of the thing you've assigned to it (again, either the type of one of its implementers, or a pointer to one of those types).
You can print the type of an interface variable with %T, and its value with %v:
func main() {
var i SomeInterface
fmt.Printf("%T, %v\n", i, i) // Prints <nil>, <nil>
var someStruct SomeStruct
i = someStruct
fmt.Printf("%T, %v\n", i, i) // Prints main.SomeStruct, {}
var someStructPtr *SomeStruct
i = someStructPtr
fmt.Printf("%T, %v\n", i, i) // Prints *main.SomeStruct, <nil>
}
Now, whenever you compare h.SomeObject == nil, the comparison will only be evaluated as true if both the types and values of the two operands match. In your case, the value of h.SomeObject is clearly <nil> (after all, the value of someStruct is surely <nil>, and you store its value in h.SomeObject). The type of h.SomeObject, based on what I just explaind, must be *SomeStruct. The value of nil is obviously <nil>.
However, what is the type of nil?
Well, nil can take on many types, and the compiler has to decide what type it should take on for each usage. When it comes to comparisons and assignments, it simply takes on the type of the thing it is being compared to or assigned to. For instance, if you are comparing an integer pointer to nil, then the nil in such a case will be of type *int.
But all of this has to be decided at compile time, and a variable referring to an interface can change types during runtime. So when you compare a variable referring to an interface to nil, what type does the compiler give to the nil operand in such a case? Well, it gives it the only sensible type, <nil>.
For a final example, consider the following code:
func main() {
var p *SomeStruct = nil // = nil is optional; pointers default to nil
var i SomeInterface = p
printf("%t\n", p == nil) // Prints true
printf("%t\n", p == i) // Prints true
printf("%t\n", i == nil) // Prints false
}
p == nil is true, since p is of type *SomeStruct with value <nil>, and nil (in this case) is also of type *SomeStruct with value <nil>.
p == i is true, since i is also of type *SomeStruct with value <nil> (it is simply storing the type and value of p).
However, i == nil is false, because nil, in this case, takes on the type <nil> rather than *SomeStruct.
The solution around this problem is simply to never store something of value <nil> in an interface-referring variable, except for nil itself. That way, whenever the value of the interface-referring variable is <nil>, its type will also be <nil>, and comparisons against nil will work as expected. For this reason, you often see code that looks like this:
if p == nil {
i = nil
} else {
i = p
}

golang (*interface{})(nil) is nil or not?

the code snippet is the following:
package main
import (
"fmt"
"reflect"
)
func main() {
a := (*interface{})(nil)
fmt.Println(reflect.TypeOf(a), reflect.ValueOf(a))
var b interface{} = (*interface{})(nil)
fmt.Println(reflect.TypeOf(b), reflect.ValueOf(b))
fmt.Println(a == nil, b == nil)
}
the output like below:
*interface {} <nil>
*interface {} <nil>
true false
so var interface{} is different from :=,why?
according to golang faq
Under the covers, interfaces are implemented as two elements, a type and a value. The value, called the interface's dynamic value, is an arbitrary concrete value and the type is that of the value. For the int value 3, an interface value contains, schematically, (int, 3).
An interface value is nil only if the inner value and type are both unset, (nil, nil). In particular, a nil interface will always hold a nil type. If we store a nil pointer of type *int inside an interface value, the inner type will be *int regardless of the value of the pointer: (*int, nil). Such an interface value will therefore be non-nil even when the pointer inside is nil.
a := (*interface{})(nil) is equal with var a *interface{} = nil.
but var b interface{} = (*interface{})(nil) , mean b is type interface{}, and interface{} variable only nil when it's type and value are both nil, obviously type *interface{} is not nil.

Type declaration importance in golang, nil values [duplicate]

This question already has answers here:
Hiding nil values, understanding why Go fails here
(3 answers)
Closed 6 years ago.
I have this small golang test I cannot understand:
package main
import "fmt"
type myObj struct {
}
func nilObj() *myObj {
return nil
}
func nilInt() interface{} {
return nil
}
func main() {
var obj1 interface{}
fmt.Println(obj1 == nil) // true
obj1 = nilObj()
fmt.Println(obj1 == nil) // false
var obj2 *myObj
fmt.Println(obj2 == nil) // true
obj2 = nilObj()
fmt.Println(obj2 == nil) // true
var obj3 interface{}
fmt.Println(obj3 == nil) // true
obj3 = nilInt()
fmt.Println(obj3 == nil) // true
}
Between obj1 and obj2, only the variable declaration changes, but the result is different.
Between obj1 and obj3, the function call does not return the same type (struct pointer vs interface). I am not entirely sure I understand the result.
Any help is welcome (https://play.golang.org/p/JcjsJ-_S8I)
Under the covers, interfaces are implemented as two elements, a type and a value. The value, called the interface's dynamic value, is an arbitrary concrete value and the type is that of the value. For the int value 3, an interface value contains, schematically, (int, 3).
An interface value is nil only if the inner value and type are both unset, (nil, nil). In particular, a nil interface will always hold a nil type. If we store a nil pointer of type *int inside an interface value, the inner type will be *int regardless of the value of the pointer: (*int, nil). Such an interface value will therefore be non-nil even when the pointer inside is nil.
https://golang.org/doc/faq#nil_error

This nil instance of a struct, that satisfies the error interface, is not showing as nil

This should be a gimme for someone. Why do I not get what I expect ("Error is not nil") here?
http://play.golang.org/p/s8CWQxobVL
type Goof struct {}
func (goof *Goof) Error() string {
return fmt.Sprintf("I'm a goof")
}
func TestError(err error) {
if err == nil {
fmt.Println("Error is nil")
} else {
fmt.Println("Error is not nil")
}
}
func main() {
var g *Goof // nil
TestError(g) // expect "Error is nil"
}
This is, it turns out, a Frequently Asked Question about Go, and the short answer is that interface comparisons compare the type and the value, and (*Goof)(nil) and error(nil) have different types.
Since if err != nil is standard, you want a return value that'll work with it. You could declare var err error instead of var g *Goof: err's zero value is conveniently error(nil)
Or, if your func returns an error, return nil will return what you want.
For more background, here's the start of the FAQ's answer:
Under the covers, interfaces are implemented as two elements, a type and a value. The value, called the interface's dynamic value, is an arbitrary concrete value and the type is that of the value. For the int value 3, an interface value contains, schematically, (int, 3).
An interface value is nil only if the inner value and type are both unset, (nil, nil). In particular, a nil interface will always hold a nil type. If we store a pointer of type *int inside an interface value, the inner type will be *int regardless of the value of the pointer: (*int, nil). Such an interface value will therefore be non-nil even when the pointer inside is nil.
And == is strictly checking if the types are identical, not if a type (*Goof) implements an interface (error). Check out the original for more.
If it helps clarify, this doesn't only happen with nil: in this example, the data underlying the x and y variables is obviously 3, but they have different types. When you put x and y into interface{}s, they compare as unequal:
package main
import "fmt"
type Bob int
func main() {
var x int = 3
var y Bob = 3
var ix, iy interface{} = x, y
fmt.Println(ix == iy)
}

Resources