Golang中map的map和带map的结构体该如何选择?
Golang中map的map和带map的结构体该如何选择? 我正在从数据库中提取以下形式的数据: 客户,月份,销售额 ACME公司,01,7500 ABC公司,01,2500 等等… 现在我想要在Go语言中将其添加到合适的载体中。但我不确定最佳的前进方式是什么,是使用结构体还是使用嵌套映射。
到目前为止我尝试了结构体的方式,但我一定是遗漏了什么?
type monthlytotal struct {
client string
month map[string]string
}
var months, clients, sales string
for result.Next() {
err := result.Scan(&months, &clients, &sales)
if err != nil {
log.Fatal(err)
}
c := new(monthlytotal)
c.client = clients
c.month = make(map[string]string)
c.month[months] = sales
}
这是最佳方式吗?现在如何遍历所有客户并访问映射以打印类似这样的内容?:
ACME 01,7500 ACME 02,7700 等等… ABC公司 01 2500 等等…
更多关于Golang中map的map和带map的结构体该如何选择?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这个方法立刻奏效了,谢谢!
由于每个客户端都会有多个(月份,销售额)组合,我认为一个比较好的处理方式是使用 map[string][]struct。其中客户端作为键,包含月份和销售额的结构体作为值。(根据我对您问题的理解)
例如:
type monthlytotal struct{
month string
sale string
}
.
.
.
var clientMap = make(map[string][]monthlytotal)
var month, client, sale string
for result.Next() {
err := result.Scan(&month, &client, &sale)
if err != nil {
log.Fatal(err)
}
var out = monthlytotal{
month: month,
sale: sale,
}
clientMap[client] = append(clientMap[client], out)
}
for c, outSlice := range clientMap{
for _, v := range outSlice{
// c 是客户端,v 是切片中的每个元素
fmt.Println(c, v.month, v.sale)
}
}
类似这样的方法应该可行。我有一段时间没接触数据库了,但觉得这个方案应该能满足需求。如果有任何问题请告诉我。
对于你的数据结构需求,使用嵌套映射是更合适的选择。你的结构体方法存在几个问题:每个monthlytotal实例都会覆盖之前的月份数据,而且无法有效存储多个客户的数据。
以下是更优的解决方案:
推荐方案:嵌套映射
// 使用 map[string]map[string]string
// 外层map: 客户 -> 月份映射
// 内层map: 月份 -> 销售额
data := make(map[string]map[string]string)
for result.Next() {
var client, month, sales string
err := result.Scan(&client, &month, &sales)
if err != nil {
log.Fatal(err)
}
// 如果客户不存在,创建内层map
if data[client] == nil {
data[client] = make(map[string]string)
}
// 添加月份销售额数据
data[client][month] = sales
}
遍历和打印数据
// 按客户遍历
for client, monthlyData := range data {
// 按月份遍历每个客户的数据
for month, sales := range monthlyData {
fmt.Printf("%s %s, %s\n", client, month, sales)
}
}
替代方案:带映射的结构体切片
如果你需要更结构化的方式,可以考虑:
type ClientData struct {
Name string
Sales map[string]string // 月份 -> 销售额
}
clients := make([]ClientData, 0)
clientMap := make(map[string]int) // 客户名 -> 切片索引
for result.Next() {
var client, month, sales string
err := result.Scan(&client, &month, &sales)
if err != nil {
log.Fatal(err)
}
// 检查客户是否已存在
if idx, exists := clientMap[client]; exists {
clients[idx].Sales[month] = sales
} else {
// 新客户
newClient := ClientData{
Name: client,
Sales: make(map[string]string),
}
newClient.Sales[month] = sales
clients = append(clients, newClient)
clientMap[client] = len(clients) - 1
}
}
// 遍历打印
for _, client := range clients {
for month, sales := range client.Sales {
fmt.Printf("%s %s, %s\n", client.Name, month, sales)
}
}
性能考虑
对于你的用例,简单的嵌套映射方案更简洁高效:
- 查找时间复杂度:O(1)
- 内存使用更优
- 代码更简洁
嵌套映射方案能直接满足你的数据存储和遍历需求,是最佳选择。

