英文:
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), ",") {
// ...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论