在 Golang 中,循环内部追加操作会重复最后一个值。

huangapple go评论81阅读模式
英文:

Appending inside a loop repeats the last value in Golang

问题

在尝试将迭代的值附加到Go中时,该函数会将最后一个迭代附加四次。例如,我试图将包含网络卡数据的字符串解析为映射,但在迭代时只附加最后一个:

以下是包含代码的playground链接:
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{})

	// Loop through network cards
	for _, Cards := range strings.Split(string(NetworkJson), ",[") {

		// Loop through data of each card
		for _, CardData := range strings.Split(string(Cards), ",") {

			// Check if data starts with whitespace
			if strings.HasPrefix(CardData, " ") {

				// Check if data without whitespace starts with [
				if strings.HasPrefix(strings.TrimSpace(CardData), "[") {

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

					// If it doesn't start with [, check if it contains :
				} else if strings.Contains(CardData, ":") {

					// Get remaining data
					Data = strings.Split(strings.TrimSpace(string(CardData)), ":")
					CardMap[Data[0]] = strings.TrimSpace(Data[1])

				}

			}

		}

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

			// Assign data
			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"])
	}
}
英文:

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"])
	}
}

答案1

得分: 1

你将所有内容都存储在同一个名为CardMap的映射变量中,并且使用了一个名为"Card Name"的单一键。append(NetCard["Cards"], CardMap)并没有对CardMap进行深拷贝,只是追加了一个浅拷贝,因此浅拷贝的数据在每次迭代时都被更新。你的其他变量也有同样的问题。

将变量声明移到主循环中:

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

英文:

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

huangapple
  • 本文由 发表于 2022年3月11日 19:07:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/71437577.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定