我有客户与 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/