通过函数将指针设置为nil

There is a function that sets a pointer to a nil value:

func nilSetter(x *int) {
    x = nil
}

I have such snippet of code:

i := 42
fmt.Println(&i)
nilSetter(&i)
fmt.Println(&i)

Which prints:

0xc42008a000
0xc42008a000

While I expect:

0xc42008a000
nil

I know that it happens because function nilSetter just copy address and sets to nil that copy.

But how can I do it correctly?

The only way to achieve that is with a pointer to a pointer. And it's pretty clunky so it's probably not what you want:

func nilSetter(x **int) {
    *x = nil
}

func main() {
    x := 2
    xp := &x

    fmt.Println(xp)
    nilSetter(&xp)
    fmt.Println(xp)

}

// Output:
// 0x10414020
// <nil>

The reason of such behaviour is because there is no pass by reference in Go.

Two variables can have contents that point to the same storage location. But, it is not possible to have them share the same storage location. Example:

package main

import "fmt"

func main() {
        var a int
        var b, c = &a, &a
        fmt.Println(b, c)   // 0x1040a124 0x1040a124
        fmt.Println(&b, &c) // 0x1040c108 0x1040c110
}

From your code, the argument x of nilSetter is pointing to some location but it have its own address and when you are setting a nil to it, you are changing its address not the address of what it is pointing to.

package main

import "fmt"

func nilSetter(x *int) {
    x = nil
    fmt.Println(x, &x) // <nil> 0x1040c140
}

func main() {
    i := 42
    fmt.Println(&i) // 0x10414020
    nilSetter(&i)
    fmt.Println(&i) // 0x10414020
}

That is why pointers always have an exact address even its value is nil

Referencing to a blog post by Dave Cheney: https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go

Just use return value and assign.

func nilSetter(x *int) *int {
    x = nil
    return x
}

x = nilSetter(x)