go

WTF is nil ?

nil Is the zero value for pointers, interfaces, maps, slices, channels and function types, representing an uninitialized value.

nil serves a similar purpose in the language’s type system.

var p *int         // p is a nil pointer
var s []int        // s is a nil slice
var m map[string]int // m is a nil map
var ch chan int    // ch is a nil channel
var fn func()      // fn is a nil function
var i interface{}  // i is a nil interface
 
fmt.Println(p == nil)  // true
fmt.Println(s == nil)  // true

Tip

nil is usually mistaken as null (or NULL) in other languages, but they are different.
nil can be used without declaring it.

nil != null

import "fmt"
 
func main() {
	// Your code goes here inside the main function
	var ptr *int
	fmt.Println(ptr) // Outputs: <nil>
 
	// var n = nil // nil is untyped
 
	isNil()
}
 
func isNil() {
	var i *int = nil
	var j *int = nil
	if i == j {
		fmt.Println("equal")
	} else {
		fmt.Println("no")
	}
}
 
// Output
// <nil>
// equal

nil Can represent Zero values of the following kinds of types:

  • pointer types

  • map types

  • slice types

  • function types

  • channel types

  • interface types

  • Predeclared nil has not a Default type.

    • the default types of true and false are both bool type.
  • nil Is not a keyword.(BTW, null and NULL in many other languages are also not keywords.)

	nil := 123
	fmt.Println(nil) // 123
  • The Sizes of Nil Values With Types of Different Kinds May Be Different

nil is Untyped

nil has no default type on its own. You must assign it to something that has a type, and then it takes on that context.

var p *int = nil        // now `nil` is treated as *int
var s []string = nil    // now `nil` is treated as []string
var ch chan int = nil   // now `nil` is treated as chan int
 
fmt.Println(nil) // ❌ ERROR: use of untyped nil

Usage

1. Pointers

nil represents a pointer that does not point to any memory location. A nil pointer does not hold a valid memory address.

  • Example:
var ptr *int // ptr is nil by default
if ptr == nil {
    fmt.Println("Pointer is nil")
}

2. Interfaces

var i interface{}
if i == nil {
    fmt.Println("Interface is nil")
}

3. Slices

var s []int
if s == nil {
	fmt.Println("Slice is nil")
}

6. Functions

var f func()
if f == nil {
    fmt.Println("Function is nil")
}

7. Error Handling

func someFunc() error {
    // Do something
    return nil // No error
}

WTF is _ Blank Identifier ?

Effective Go - The Go Programming Language

  • The blank identifier can be assigned or declared with any value of any type, with the value discarded harmlessly.
  • It’s a bit like writing to the Unix /dev/null file.
  • it represents a write-only value to be used as a place-holder where a variable is needed but the actual value is irrelevant.

1. Ignoring Unused Return Values

value, _ := someFunction() // Ignore the second return value

2. Ignoring Errors

result, _ := strconv.Atoi("123") // Ignore the error for simplicity

3. Loop Iteration without Index

values := []int{10, 20, 30}
for _, v := range values {
    fmt.Println(v) // Only using the value, ignoring the index
}

4. Assigning to Blank Identifier to Avoid “Declared But Not Used” Error

result := someComputation()
_ = result // Avoid unused variable error

5. Ignoring Values in map Ranges

myMap := map[string]int{"a": 1, "b": 2}
	for _, v := range myMap {
        fmt.Println(v) // Only using the value, ignoring the key
}

6. Implementing Interfaces Partially

var _ SomeInterface = (*MyStruct)(nil) // Ensures MyStruct implements SomeInterface

7. Using Blank Identifier with import to Import a Package for Side Effects Only

import _ "net/http/pprof" // Import for side effects only

8. Placeholder in Multiple Assignment (Sometimes)

a, _, c := someFunc() // Ignore the second value