Appending inside a loop repeats the last value in Golang

Issue

When trying to append the values of an iteration in go, the function is appending the last iteration 4 times. For example, i’m trying to parse a string containing network cards data into a map, and when iterating it only appends the last one:

Here’s the playground link with the code:
https://go.dev/play/p/mKtFvK36PMn

package main

import (
    "fmt"
    "strings"
)

type Foo struct {
    val int
}

func main() {

    NetworkJson := "4 NIC(s) Installed.,[01]: Realtek PCIe GbE Family Controller,      Connection Name: Ethernet,      DHCP Enabled:    Yes,      DHCP Server:     10.101.10.13,      IP address(es),      [01]: 10.1.2.62,[02]: VirtualBox Host-Only Ethernet Adapter,      Connection Name: VirtualBox Host-Only Network,      DHCP Enabled:    No,      IP address(es),      [01]: 192.168.56.1,      [02]: fe80::4c17:978a:2c91:8e27,[03]: VMware Virtual Ethernet Adapter for VMnet1,      Connection Name: VMware Network Adapter VMnet1,      DHCP Enabled:    Yes,      DHCP Server:     192.168.146.254,      IP address(es),      [01]: 192.168.146.1,      [02]: fe80::88b4:d443:2ab8:59b5,[04]: VMware Virtual Ethernet Adapter for VMnet8,      Connection Name: VMware Network Adapter VMnet8,      DHCP Enabled:    Yes,      DHCP Server:     192.168.128.254,      IP address(es),      [01]: 192.168.128.1,      [02]: fe80::a40d:e64:fa9f:e82f"
    var IPs []string
    var Data []string
    var IPMap = make(map[string]string)
    var CardMap = make(map[string]interface{})
    var CardIP = make(map[string][]map[string]string)
    var NetCard = make(map[string][]interface{})

    // Faz loop entre as placas de rede
    for _, Cards := range strings.Split(string(NetworkJson), ",[") {

        // Faz loop entre os dados de cada placa
        for _, CardData := range strings.Split(string(Cards), ",") {

            // Verifica se dado inicia com espaço em branco
            if strings.HasPrefix(CardData, " ") {

                // Verifica se dado sem o espaço em branco começa com [
                if strings.HasPrefix(strings.TrimSpace(CardData), "[") {

                    // Pega IPS
                    IPs = strings.Split(strings.TrimSpace(string(CardData)), ": ")
                    IPMap[string(IPs[0])] = strings.TrimSpace(string(IPs[1]))

                    // Se não iniciar com [ verifica se contém :
                } else if strings.Contains(CardData, ":") {

                    // Pega restante dos dados
                    Data = strings.Split(strings.TrimSpace(string(CardData)), ":")
                    CardMap[Data[0]] = strings.TrimSpace(Data[1])

                }

            }

        }

        if strings.Contains(Cards, "]") {

            // Aloca dados
            CardMap["Card Name"] = string(strings.SplitN(string(Cards), ",", 2)[0])[5:]
            CardIP["IP Adress(es)"] = append(CardIP["IP Adress(es)"], IPMap)
            CardMap["IP Adress(es)"] = CardIP["IP Adress(es)"]
            CardIP["IP Adress(es)"] = CardIP["IP Adress(es)"][:0]

            NetCard["Cards"] = append(NetCard["Cards"], CardMap)
            fmt.Println(CardMap)

        }
        fmt.Println(NetCard["Cards"])
    }
}

Solution

You are storing everything into the same map variable CardMap and you are using a singular key "Card Name". The append(NetCard["Cards"], CardMap) does not do a deep copy of the CardMap, only a shallow copy is appended and therefore the shallow copy’s data is being update on every iteration. Your other variables have the same problem.

Move the variable declaration into the main loop:

var NetCard = make(map[string][]interface{})

// Faz loop entre as placas de rede
for _, Cards := range strings.Split(string(NetworkJson), ",[") {

    var IPs []string
    var Data []string
    var IPMap = make(map[string]string)
    var CardMap = make(map[string]interface{})
    var CardIP = make(map[string][]map[string]string)

    // Faz loop entre os dados de cada placa
    for _, CardData := range strings.Split(string(Cards), ",") {
        // ...

https://go.dev/play/p/VE_VWOsvsna

Answered By – mkopriva

Answer Checked By – Gilberto Lyons (GoLangFix Admin)

Leave a Reply

Your email address will not be published.