Golang range iterator of pointer

It’s tricky to using pointer in range iterator.

Please beware variable “hostStatus” is a pointer that’s been reused in each iteration. the location of hostStatus will be the same although it points to a different struct in each iteration.

It may cause duplicated values in the final results, beware!

package main

import (
	"fmt"
	"strings"

)


type HostStatus struct {
	Name    string
	Status  string
	Message string
}

func main() {
	value := []HostStatus{HostStatus{"1","ok","test1"}, HostStatus{"2","ok","test2"}, HostStatus{"3","ok","test3"}}
	fmt.Printf("value = %v\n", value)
	hostnameToStatus := map[string]HostStatus{}
	hostnameToStatusP := map[string]*HostStatus{}
	hostnameToStatusP2 := map[string]*HostStatus{}
	for k, hostStatus := range value {
		hostnameToStatus[hostStatus.Name] = hostStatus
		hostnameToStatusP[hostStatus.Name] = &value[k]
		hostnameToStatusP2[hostStatus.Name] = &hostStatus
		fmt.Printf("%s , p= %p\n", hostStatus.Name, &hostStatus)
	}
	fmt.Print("--1--\n")
	for k, v := range hostnameToStatus {
		fmt.Printf("%s = %s\n", k, v)
	}
	fmt.Print("--2--\n")
	for k, v := range hostnameToStatusP {
		fmt.Printf("%s = %s\n", k, v)
	}
	fmt.Print("--3--\n")
	for k, v := range hostnameToStatusP2 {
		fmt.Printf("%s = %v\n", k, v)
		fmt.Printf("%s = %p\n", k, &v)
	}

	successfulChildHostList := []string{}
	merged := []HostStatus{}
	for _, hostStatus := range hostnameToStatusP {
		merged = append(merged, *hostStatus)
		if strings.EqualFold(hostStatus.Status, "yes") {
			successfulChildHostList = append(successfulChildHostList, hostStatus.Name)
		}
	}
	fmt.Print("-----------\n")
	fmt.Printf("merged = %v\n", merged)
	fmt.Printf("successfulChildHostList = %v\n", successfulChildHostList)

}

Results, see the 3rd one with duplicated values.:

value = [{1 ok test1} {2 ok test2} {3 ok test3}]
1 , p= 0xc000068210
2 , p= 0xc000068210
3 , p= 0xc000068210
--1--
3 = {3 ok test3}
1 = {1 ok test1}
2 = {2 ok test2}
--2--
1 = &{1 ok test1}
2 = &{2 ok test2}
3 = &{3 ok test3}
--3--
1 = &{3 ok test3}
1 = 0xc00000e030
2 = &{3 ok test3}
2 = 0xc00000e030
3 = &{3 ok test3}
3 = 0xc00000e030
-----------
merged = [{1 ok test1} {2 ok test2} {3 ok test3}]
successfulChildHostList = []

Leave a Reply

Your email address will not be published.