Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Passing pointer of string to a function leads to the wrong string being printed

I have the following program (simplified as much as possible):

package main

import "fmt"

type Test struct {
    Str *string
}

func main() {
    arr := []string{"vanC", "vanD"}

    arr2 := make([]Test, 0)
    for _, element := range arr {
        fmt.Println(element, &element)

        arr2 = append(arr2, Test{
            Str: &element,
        })
    }

    fn(arr2)
}

func fn(arr2 []Test) {
    for _, element := range arr2 {
        fmt.Println(*element.Str)
    }
}

Playground

As you can see, I am building a slice consisting of a struct containing a pointer to a string. I need this pointer to be able to pass nil as the strings are optional.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

The output of this program is not at all what I am expecting.

Output:

vanC 0xc00009e220
vanD 0xc00009e220
vanD               // Why "vanD" here?
vanD

Expected:

vanC 0xc00009e220
vanD 0xc00009e220
vanC
vanD

I don’t see any reason why vanD is printed twice and why vanC is not printed at all inside fn. Seeking an explanation and how to fix this.

>Solution :

The loop variables are declared once, and overwritten at every iteration. You are adding the address of element, which remains fixed throughout the iteration, hence you add it twice. When you loop at the contents after the loop, what you see is two copies with the latest value.

You can add a copy to the slice:

for _, element := range arr {
        element:=element // Copy and redeclare
        fmt.Println(element, &element)

        arr2 = append(arr2, Test{
            Str: &element,
        })
    }

Or add it by its address in the slice:

for i, element := range arr {
        arr2 = append(arr2, Test{
            Str: &arr[i],
        })
    }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading