Why is this zero length and zero capacity slice not nil? - go

I'm going through a Go tutorial and I reached the lesson about nil slices where it says:
A nil slice has a length and capacity of 0 and has no underlying array.
In order to show this they present this code which works
package main
import "fmt"
func main() {
var s []int
fmt.Println(s, len(s), cap(s))
if s == nil {
fmt.Println("nil!")
}
}
However, I tried to experiment and I replaced var s []int with s := []int{}. The console still prints [] 0 0 as in the first case but no longer the nil! string. So why is the first one nil and the other one not?

For s := []int{}:
Because it is initialized to a new type (e.g. struct) with an underlying array, a length, and a capacity
A slice, once initialized, is always associated with an underlying array that holds its elements.
For var s []int see Slice types:
The value of an uninitialized slice is nil.
The zero value:
When storage is allocated for a variable, either through a declaration or a call of new, or when a new value is created, either through a composite literal or a call of make, and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for numeric types, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.
These two simple declarations are equivalent:
var i int
var i int = 0
After
type T struct { i int; f float64; next *T }
t := new(T)
the following holds:
t.i == 0
t.f == 0.0
t.next == nil
The same would also be true after
var t T
I hope this helps.

Related

how to append nil to dynamic type slice by reflect.Append

Code below will raise a runtime error when append reflect.Value of nil:
package main
import (
"fmt"
"reflect"
)
func main() {
var list []interface{}
v := reflect.ValueOf(list)
v = reflect.Append(v, reflect.ValueOf(1)) // [1]
v = reflect.Append(v, reflect.ValueOf("1")) // [1, 1]
v = reflect.Append(v, reflect.ValueOf(nil)) // runtime error
fmt.Println(v)
}
So
why there is a runtime error?
how can I use reflect.Append to add a nil to interface{} slice?
interface{} is an interface type, and they are "tricky". They are wrappers around a concrete value and the concrete type, schematically a (value, type) pair.
So when you pass a concrete value to a function that expects an interface{} value, the concrete value will be wrapped in an interface{} value automatically, implicitly. If you pass a nil to such a function, the interface value itself will be nil. If you pass a nil pointer to it, such as (*int)(nil), the interface value will not be nil but an interface value holding "(nil, *int)".
If you pass nil to reflect.ValueOf(), it results in a "zero" reflect.Value which represents no value at all. If you pass this to reflect.Append(), it will not have the type information, it will not know what you want to append to the slice.
It is possible to create a value that represents the nil interface value.
To do that, we may start from the type descriptor of a value of an interface pointer (pointers to interface rarely makes sense, but this is one of them). We navigate to the type descriptor of the pointed type, which is interface{}. We obtain a zero value of this type (using reflect.Zero()), which is nil (zero value of interface types is nil).
Zero returns a Value representing the zero value for the specified type. The result is different from the zero value of the Value struct, which represents no value at all.
So this is how it looks like:
typeOfEmptyIface := reflect.TypeOf((*interface{})(nil)).Elem()
valueOfZeroEmptyIface := reflect.Zero(typeOfEmptyIface)
v = reflect.Append(v, valueOfZeroEmptyIface)
Or as a single line:
v = reflect.Append(v, reflect.Zero(reflect.TypeOf((*interface{})(nil)).Elem()))
To check the results, let's use:
fmt.Printf("%#v\n", v)
And also let's type-assert back the slice, and add a nil value using the builtin append() function:
list = v.Interface().([]interface{})
list = append(list, nil)
fmt.Printf("%#v\n", list)
Let's do an explicit, extra check if the elements are nil (compare them to nil). Although using %#v verb this is redundant, %v likes to print non-nil interfaces holding nil concrete values just as nil (the same as if the interface value itself would be nil).
fmt.Println(list[2] == nil, list[3] == nil)
Ouptut will be (try it on the Go Playground):
[]interface {}{1, "1", interface {}(nil)}
[]interface {}{1, "1", interface {}(nil), interface {}(nil)}
true true
See related question: Hiding nil values, understanding why golang fails here
Also: The Go Blog: The Laws of Reflection

What value does the return value take if something is not in a map?

Ok so according to this:
How to check if a map contains a key in go?
if val, ok := m["foo"]; ok {
//do something here
}
that's fine, but how come we can't do this:
val, ok := m["foo"]
if val == nil { // cannot compare val to nil
}
I get a compilation error saying I can't compare val to nil, but then what value does val have? What can I compare it to, to determine if it exists or not?
the type of m is like:
type m map[string]struct{}
The Go Programming Language Specification
Index expressions
For a of map type M: if the map is nil or does not contain such an
entry, a[x] is the zero value for the element type of M.
The zero value
When storage is allocated for a variable, either through a declaration
or a call of new, or when a new value is created, either through a
composite literal or a call of make, and no explicit initialization is
provided, the variable or value is given a default value. Each element
of such a variable or value is set to the zero value for its type:
false for booleans, 0 for numeric types, "" for strings, and nil for
pointers, functions, interfaces, slices, channels, and maps.
The Go Programming Language Specification
Composite literals
Composite literals construct values for structs, arrays, slices, and
maps and create a new value each time they are evaluated. They consist
of the type of the literal followed by a brace-bound list of elements.
Each element may optionally be preceded by a corresponding key. For
struct literals the following rules apply:
A literal may omit the element list; such a literal evaluates to the
zero value for its type.
For your example, type struct{}, omit the element list from the composite literal, struct{}{}, for the zero value.
For example,
package main
import "fmt"
func main() {
m := map[string]struct{}{}
val, ok := m["foo"]
fmt.Printf("%T %v\n", val, val)
if val == struct{}{} {
fmt.Println("==", val, ok)
}
}
Playground: https://play.golang.org/p/44D_ZfFDA77
Output:
struct {} {}
== {} false
The Go Programming Language Specification
Variable declarations
A variable declaration creates one or more variables, binds
corresponding identifiers to them, and gives each a type and an
initial value.
If a list of expressions is given, the variables are initialized with
the expressions following the rules for assignments. Otherwise, each
variable is initialized to its zero value.
If a type is present, each variable is given that type. Otherwise,
each variable is given the type of the corresponding initialization
value in the assignment.
In your example, you could declare a variable of type struct{} with no initial value, which would be initialized to the zero value for the struct{} type.
For example,
package main
import "fmt"
func main() {
m := map[string]struct{}{}
val, ok := m["foo"]
fmt.Printf("%T %v\n", val, val)
var zeroValue struct{}
if val == zeroValue {
fmt.Println("==", val, ok)
}
}
Playground: https://play.golang.org/p/_XcSCEeEKJV
Output:
struct {} {}
== {} false
You can most certainly do what you did above. Comparing to nil depends on the type of value you have in map. If its interface{} you can compare it to nil:
m := map[string]interface{}{}
val, _ := m["foo"]
if val == nil {
fmt.Println("no index")
}

How to check if parameter passed into function is nil in Go?

Need to check if parameter being passed to func is nil and return 0.
Below is my intended code
func (t *Transaction) GetOperationCount(input bean.Request) (int, error) {
var result int = 0
if input == nil { //error here
return result, nil
}
// Other code here!!!!
return result, nil
}
bean.Reques is a struct.
However it had issue: "cannot convert nil to type bean.Request input Request". I have trying
if (bean.Request{})== input
But it gives :
"json:\"MV_STATUS\""; NDFNFFP string "json:\"NDF_NFFP\""; NDFNFMV string "json:\"NDF_NFMV\"" } "json:\"attr\"" } "json:\"marke
t_value\"" } "json:\"market_values\"" } "json:\"tick\"" } "json:\"insertion\"" } "json:\"operation\"" } "json:\"transaction\""
} cannot be compared)
Should I change the parameter to "input *bean.Request" ?
Short answer: Yes, here is the working version:
func (t *Transaction) GetOperationCount(input *bean.Request) (int, error) {
var result int = 0
if input == nil {
return result, nil
}
// Other code here
return result, nil
}
You have some options (depending to your use case, see: Pointers vs. values in parameters and return values):
1- You may use pointer (input *bean.Request) and compare it with nil
2- you may use another struct and compare it with reflect.DeepEqual(r, zero)
3- You may write your own compare function (or method with pointer or value receiver)
See this sample (try it on The Go Playground):
package main
import (
"fmt"
"reflect"
)
func (t *Transaction) GetOperationCount(input *Request) (int, error) {
var result int = 0
if input == nil {
return result, nil
}
// Other code here
return result, nil
}
func main() {
var input *Request
if input == nil {
fmt.Println("input is nil.") //input is nil.
}
input = &Request{}
if input != nil {
fmt.Println("input is not nil.") //input is not nil.
}
r := Request{}
fmt.Printf("Zero value: %#v\n", r) //Zero value: main.Request{I:0}
zero := Request{}
fmt.Println("r == zero :", r == zero) //r == zero : true
fmt.Println("DeepEqual :", reflect.DeepEqual(r, zero)) //DeepEqual : true
fmt.Println("compare :", compare(&r, &zero)) //compare : true
}
func compare(r, zero *Request) bool {
return r.I == zero.I
}
type Request struct {
I int
}
type Transaction struct{}
output:
input is nil.
input is not nil.
Zero value: main.Request{I:0}
r == zero : true
DeepEqual : true
compare : true
Comparison operators:
4- You may compare it with its zero value (nil for pointers, and if it is struct it's zero value is Empty struct if it is like struct{} (not nil), or struct with all fields initialized to their zero values):
The zero value:
When storage is allocated for a variable, either through a declaration
or a call of new, or when a new value is created, either through a
composite literal or a call of make, and no explicit initialization is
provided, the variable or value is given a default value. Each element
of such a variable or value is set to the zero value for its type:
false for booleans, 0 for integers, 0.0 for floats, "" for strings,
and nil for pointers, functions, interfaces, slices, channels, and
maps. This initialization is done recursively, so for instance each
element of an array of structs will have its fields zeroed if no value
is specified.
These two simple declarations are equivalent:
var i int
var i int = 0
After
type T struct { i int; f float64; next *T }
t := new(T)
the following holds:
t.i == 0
t.f == 0.0
t.next == nil
The same would also be true after
var t T
See "reflect.DeepEqual": How to compare struct, slice, map are equal?
func DeepEqual(x, y interface{}) bool
Docs:
DeepEqual reports whether x and y are ``deeply equal,'' defined as follows.
Two values of identical type are deeply equal if one of the following cases applies.
Values of distinct types are never deeply equal.
Array values are deeply equal when their corresponding elements are deeply equal.
Struct values are deeply equal if their corresponding fields,
both exported and unexported, are deeply equal.
Func values are deeply equal if both are nil; otherwise they are not deeply equal.
Interface values are deeply equal if they hold deeply equal concrete values.
Map values are deeply equal if they are the same map object
or if they have the same length and their corresponding keys
(matched using Go equality) map to deeply equal values.
Pointer values are deeply equal if they are equal using Go's == operator
or if they point to deeply equal values.
Slice values are deeply equal when all of the following are true:
they are both nil or both non-nil, they have the same length,
and either they point to the same initial entry of the same underlying array
(that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal.
Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil))
are not deeply equal.
Other values - numbers, bools, strings, and channels - are deeply equal
if they are equal using Go's == operator.
In general DeepEqual is a recursive relaxation of Go's == operator.
However, this idea is impossible to implement without some inconsistency.
Specifically, it is possible for a value to be unequal to itself,
either because it is of func type (uncomparable in general)
or because it is a floating-point NaN value (not equal to itself in floating-point comparison),
or because it is an array, struct, or interface containing
such a value.
On the other hand, pointer values are always equal to themselves,
even if they point at or contain such problematic values,
because they compare equal using Go's == operator, and that
is a sufficient condition to be deeply equal, regardless of content.
DeepEqual has been defined so that the same short-cut applies
to slices and maps: if x and y are the same slice or the same map,
they are deeply equal regardless of content.
Yes..The error itself mentions that it cannot compare both. You can use pointer to compare with nil or create an empty struct to compare.

What does nil mean in golang?

There are many cases using nil in golang. For example:
func (u *URL) Parse(ref string) (*URL, error) {
refurl, err := Parse(ref)
if err != nil {
return nil, err
}
return u.ResolveReference(refurl), nil
}
but we can't use it like this:
var str string //or var str int
str = nil
the golang compiler will throw a can't use nil as type string in assignment error.
Looks like nil can only be used for a pointer of struct and interface. If that is the case, then what does it mean?
and when we use it to compare to the other object, how do they compare, in other words, how does golang determine one object is nil?
EDIT:For example, if an interface is nil, its type and value must be nil at the same time. How does golang do this?
In Go, nil is the zero value for pointers, interfaces, maps, slices, channels and function types, representing an uninitialized value.
nil doesn't mean some "undefined" state, it's a proper value in itself. An object in Go is nil simply if and only if it's value is nil, which it can only be if it's of one of the aforementioned types.
An error is an interface, so nil is a valid value for one, unlike for a string. For obvious reasons a nil error represents no error.
nil in Go is simply the NULL pointer value of other languages.
You can effectively use it in place of any pointer or interface (interfaces are somewhat pointers).
You can use it as an error, because the error type is an interface.
You can't use it as a string because in Go, a string is a value.
nil is untyped in Go, meaning you can't do that:
var n = nil
Because here you lack a type for n. However, you can do
var n *Foo = nil
Note that nil being the zero value of pointers and interfaces, uninitialized pointers and interfaces will be nil.
nil is also a value but only difference is- it is empty.
In Javascript for the un-initialized variable will be undefined. In the same way Golang has nil as default value for all the un-initalized data types.
nil in Go means a zero value for pointers, interfaces, maps, slices, and channels.
It means the value is uninitialized
For the data types like slice and pointers which "refer" to other types, "nil" indicates that the variable does not refer to an instance (equivalent of null pointer in other languages)
It is thee zero value of the variables of type functions, maps, interfaces, channels and structures
nil is a predeclared identifier in Go that represents zero values for pointers, interfaces, channels, maps, slices and function types.
nil being the zero value of pointers and interfaces, uninitialized pointers and interfaces will be nil.
In Go, string can’t be nil. A string doesn’t qualify to be assigned nil.
a := nil // It will throw an error 'use of untyped nil'
var a *int = nil //It will work
In Go nil is predeclared identifier that represents nothing for pointers, interfaces, channels, maps, slices and function types. Uninitialized pointers and interfaces will be nil. A string doesn’t qualify to be either of the above-mentioned types and hence can’t be assigned nil.
If you declare a variable by shorthand decleration like this: variable:=nil this will give compile time error because compiler has no idea which type it has to assign to variable .
In Go map, slice and function doesn't support comparison but can be compared with nil.
If any two map, slice or function are assigned to nil and compared with each other then it will raise runtime error.
But if we assign nil to any two pointer variables and compare them with each other then no error will occur.
package main
import (
"fmt"
)
func main() {
var i *int =nil
var j *int =nil
if i==j {
fmt.Println("equal")
} else {
fmt.Println("no")
}
}
This code works fine and prints output as equal.
In Golang, datatype can use nil is pointers, interfaces, maps, slices, channels, function types and errors
in String value is ""
in INT value is ZERO
In Golang, zero value is the default value for defined variables. The default value of different datatypes are:
0 for integer types
0.0 for floating types
false for boolean types
"" for string types
nil for interfaces, slices, channels, maps, pointers and functions
So, nil is the zero value or default value for interfaces, slices, channels, maps, pointers and functions.
For example,
var a int
var s []int
var s1 []int = []int{1, 2}
fmt.Println(a == nil) // throw error
// invalid operation: a == nil (mismatched types int and untyped nil)
fmt.Println(s == nil) // true
fmt.Println(s1 == nil) // false
Since error is an interface, we can write
_, err := Parse("")
if err != nil { // if there is an error
// handle error
}

nil detection in Go

I see a lot of code in Go to detect nil, like this:
if err != nil {
// handle the error
}
however, I have a struct like this:
type Config struct {
host string
port float64
}
and config is an instance of Config, when I do:
if config == nil {
}
there is compile error, saying:
cannot convert nil to type Config
The compiler is pointing the error to you, you're comparing a structure instance and nil. They're not of the same type so it considers it as an invalid comparison and yells at you.
What you want to do here is to compare a pointer to your config instance to nil, which is a valid comparison. To do that you can either use the golang new builtin, or initialize a pointer to it:
config := new(Config) // not nil
or
config := &Config{
host: "myhost.com",
port: 22,
} // not nil
or
var config *Config // nil
Then you'll be able to check if
if config == nil {
// then
}
In addition to Oleiade, see the spec on zero values:
When memory is allocated to store a value, either through a declaration or a call of make or new, and no explicit initialization is provided, the memory is given a default initialization. Each element of such a value is set to the zero value for its type: false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.
As you can see, nil is not the zero value for every type but only for pointers, functions, interfaces, slices, channels and maps. This is the reason why config == nil is an error and
&config == nil is not.
To check whether your struct is uninitialized you'd have to check every member for its
respective zero value (e.g. host == "", port == 0, etc.) or have a private field which
is set by an internal initialization method. Example:
type Config struct {
Host string
Port float64
setup bool
}
func NewConfig(host string, port float64) *Config {
return &Config{host, port, true}
}
func (c *Config) Initialized() bool { return c != nil && c.setup }
I have created some sample code which creates new variables using a variety of ways that I can think of. It looks like the first 3 ways create values, and the last two create references.
package main
import "fmt"
type Config struct {
host string
port float64
}
func main() {
//value
var c1 Config
c2 := Config{}
c3 := *new(Config)
//reference
c4 := &Config{}
c5 := new(Config)
fmt.Println(&c1 == nil)
fmt.Println(&c2 == nil)
fmt.Println(&c3 == nil)
fmt.Println(c4 == nil)
fmt.Println(c5 == nil)
fmt.Println(c1, c2, c3, c4, c5)
}
which outputs:
false
false
false
false
false
{ 0} { 0} { 0} &{ 0} &{ 0}
In Go 1.13 and later, you can use Value.IsZero method offered in reflect package.
if reflect.ValueOf(v).IsZero() {
// v is zero, do something
}
Apart from basic types, it also works for Array, Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer, and Struct. See this for reference.
You can also check like struct_var == (struct{}). This does not allow you to compare to nil but it does check if it is initialized or not. Be careful while using this method. If your struct can have zero values for all of its fields you won't have great time.
package main
import "fmt"
type A struct {
Name string
}
func main() {
a := A{"Hello"}
var b A
if a == (A{}) {
fmt.Println("A is empty") // Does not print
}
if b == (A{}) {
fmt.Println("B is empty") // Prints
}
}
http://play.golang.org/p/RXcE06chxE
The language spec mentions comparison operators' behaviors:
comparison operators
In any comparison, the first operand must be assignable to the type
of the second operand, or vice versa.
Assignability
A value x is assignable to a variable of type T ("x is assignable to
T") in any of these cases:
x's type is identical to T.
x's type V and T have identical underlying types and at least one of V or T is not a named type.
T is an interface type and x implements T.
x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not
a named type.
x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
x is an untyped constant representable by a value of type T.

Resources