戈朗 : How can I populate a multi-struct map in a loop?

标签 go

我有客户与 API 交互的日志文件。我想解析这些日志并将结果提供给结构映射,以便我可以将数据组织成有用的信息。例如,我想响应以下查询:“显示每个用户每天的请求总数”。

我已经创建了一个看起来足够的结构来保存数据。但是,当我尝试运行程序时出现错误:无效操作:dates[fields[1]](type *Dates 不支持索引)[process exited with non-zero status]

http://play.golang.org/p/8u3jX26ktt

package main

import (
    "fmt"
    "strings"
)

type Stats struct {
    totalNumberOfRequests int
}
type Customer struct {
    listOfCustomers map[string]Stats // map[customerid]Stats
}
type Dates struct {
    listOfDates map[string]Customer // map[date]Customer
}

var requestLog = []string{
    "2011-10-05, 1234, apiquery",
    "2011-10-06, 1234, apiquery",
    "2011-10-06, 5678, apiquery",
    "2011-10-09, 1234, apiquery",
    "2011-10-12, 1234, apiquery",
    "2011-10-13, 1234, apiquery",
}

func main() {
    dates := new(Dates)
    for _, entry := range requestLog {
        fmt.Println("entry:", entry)
        fields := strings.Split(entry, "'")
        dates.listOfDates[fields[0]].listOfCustomers[fields[1]].totalNumberOfRequests++
    }
}

有没有更好的结构可以使用?或者有没有办法让这个结构用于这个特定目的?

最佳答案

如果我理解您对输出的期望,这里有一个解决方案。但是我不喜欢“Customer is a map with id and Stat.. I think it should be a simple struct with two Fields (cid string and stat Stats) . 此外,日期结构不允许多个客户出现在同一日期,因此我更改为将单个日期映射到用户列表。

我还添加了更多“测试场景”来涵盖客户在同一日期多次访问资源的情况。

您的示例似乎没有使用“apiquery”,因此下面的代码与它不匹配。

关于结构中指针的更改 - 参见 this issue (如您问题的评论中所述)

package main

import (
    "fmt"
    "strings"
)

type Stats struct {
    totalNumberOfRequests int
}
type Customer struct {
    customerWithStat map[string]*Stats // a customer with it's corresponding stats
}

type Dates struct {
    listOfDates map[string][]*Customer // map[date]list of customers (for each date)
}

var requestLog = []string{
    "2011-10-05, 1234, apiquery",
    "2011-10-06, 5678, apiquery",
    "2011-10-06, 1234, apiquery",
    "2011-10-06, 1234, apiquery",
    "2011-10-06, 5678, apiquery",
    "2011-10-06, 1234, apiquery",
    "2011-10-09, 1234, apiquery",
    "2011-10-12, 1234, apiquery",
    "2011-10-13, 1234, apiquery",
    "2011-10-13, 1234, apiquery",
    "2011-10-06, 1234, apiquery",
}

func main() {
    listOfDates := make(map[string][]*Customer)
    dates := Dates{listOfDates}
    for _, entry := range requestLog {
        fields := strings.Split(entry, ",")
        curDateStr := strings.TrimSpace(fields[0])
        curCustIdStr := strings.TrimSpace(fields[1])

        if customersAtDate, dateExists := dates.listOfDates[curDateStr]; dateExists {
            // Date already exist
            for _, curCustomer := range customersAtDate {
                if curStat, customerExists := curCustomer.customerWithStat[curCustIdStr]; customerExists {
                    // The user has already accessed this resource - just increment
                    curStat.totalNumberOfRequests++
                } else {
                    // New user - set access to 1
                    curCustomer.customerWithStat[curCustIdStr] = &Stats{1}
                }
            }
        } else {
            // New Date

            // Init the Statistic for the new customer
            newCustomerData := make(map[string]*Stats)
            newCustomerData[curCustIdStr] = &Stats{1}

            // Create the customer itself
            newCustomer := &Customer{newCustomerData}

            // add to the current day list
            dates.listOfDates[curDateStr] = append(dates.listOfDates[curDateStr], newCustomer)

        }
    }

    // Print result
    for date, customers := range dates.listOfDates {
        fmt.Println("Date: ", date)
        for _, customer := range customers {
            for cid, stat := range customer.customerWithStat {
                fmt.Println("  Customer: ", cid)
                fmt.Println("  # Requests: ", *stat)
            }
        }
    }
}

这将输出:

Date:  2011-10-05
  Customer:  1234
  # Requests:  {1}
Date:  2011-10-06
  Customer:  5678
  # Requests:  {2}
  Customer:  1234
  # Requests:  {4}
Date:  2011-10-09
  Customer:  1234
  # Requests:  {1}
Date:  2011-10-12
  Customer:  1234
  # Requests:  {1}
Date:  2011-10-13
  Customer:  1234
  # Requests:  {2}

关于戈朗 : How can I populate a multi-struct map in a loop?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27282602/

相关文章:

mongodb - 如何编写mongo管道

go - 写入两个独立的 channel 是否可靠地顺序进行?

go - 我如何在 Go 上模拟一个方法?

apache - apache 上的 Golang CGI

go - 与 make channel 相关的奇怪死锁

go - 为什么在 regex.ReplaceAllString() 中删除数字

go - 如何在 go.mod 中最好地声明 golang 依赖版本?

go - os.Exit 后不应该无法访问代码

go - 如何在 Golang 中使用其他文件中的其他结构方法

http - 如何通过代理服务器客户端使用自签名证书