Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does *(*int)(nil) = 0 mean in golang?

Tags:

pointers

go

I notice there is one line *(*int)(nil) = 0 in function throw

//go:nosplit
func throw(s string) {
    // Everything throw does should be recursively nosplit so it
    // can be called even when it's unsafe to grow the stack.
    systemstack(func() {
        print("fatal error: ", s, "\n")
    })
    gp := getg()
    if gp.m.throwing == 0 {
        gp.m.throwing = 1
    }
    fatalthrow()
    *(*int)(nil) = 0 // not reached
}

What does *(*int)(nil) = 0 means? and since this line *(*int)(nil) = 0 could NOT be reached, why it is here? any special usage?

like image 976
zangw Avatar asked Nov 09 '20 12:11

zangw


People also ask

What does nil mean in Golang?

nil in Go means a zero value for pointers, interfaces, maps, slices, and channels. It means the value is uninitialized.

Is zero nil in Golang?

The zero value for a number is 0 . The zero value for a pointer or interface is nil . This is the only place where nil and "zero values" really relate to each other.

What does * INT mean in Golang?

In Go a pointer is represented using the * (asterisk) character followed by the type of the stored value. In the zero function xPtr is a pointer to an int . * is also used to “dereference” pointer variables. Dereferencing a pointer gives us access to the value the pointer points to.

How do you assign nil to a variable in Golang?

We want to accept the address (pointer) of the pointer variable, which is something like **SomeType . To actually be able to assign a new value ( nil ) to the pointer variable, we have to dereference it ( * operator).


1 Answers

The line:

*(*int)(nil) = 0

Tries to dereference a nil pointer and assign a value to it, which is always a runtime panic. The code should not reach this line, ever, but if it would anyhow (e.g. a faulty code change in the future), it would panic so the error could be detected and wouldn't go unnoticed.

It's common sense to do something similar in your code too, but with a more obvious "construct" such as panic("unreachable"). For example:

func sign(a int) string {
    switch {
    case a > 0:
        return "Positive"
    case a < 0:
        return "Negative"
    case a == 0:
        return "Zero"
    default:
        panic("unreachable")
    }
}

Note that in this example this is not just to detect errors early, it's also a requirement because to the compiler there would be no guarantee that a return statement would be reached. You could also move the panic("unreachable") statement after the switch (instead of the default branch), it's a matter of taste.

If you would change the above function to not return but print the sign, it would still be a good practice to leave the default branch to panic, although it's not a requirement in this variant:

func printSign(a int) {
    switch {
    case a > 0:
        fmt.Println("Positive")
    case a < 0:
        fmt.Println("Negative")
    case a == 0:
        fmt.Println("Zero")
    default:
        panic("unreachable")
    }
}
like image 132
icza Avatar answered Oct 01 '22 03:10

icza