Golang应用程序开发遇到问题求助
Golang应用程序开发遇到问题求助 我有以下代码:
package main
import (
"encoding/json"
"fmt"
)
// JSONMap 是 map 的特化类型
type JSONMap = map[string]interface{}
// JSONAggregation 是 map[] 的特化类型
type JSONAggregation = map[string][]interface{}
// JSONtoMap 将 json 字符串转换为与 Go 兼容的 JSONMap
func JSONtoMap(originalJSON string) JSONMap {
var result map[string]interface{}
json.Unmarshal([]byte(originalJSON), &result)
return result
}
func aggregateInterfaces(aggregation *JSONAggregation, target JSONMap) {
ref := *aggregation
// 遍历每个目标(JSONMap)并将其追加到聚合中
// 如果是第一次看到该键,则分配内存
// 然后追加它
/*layout := "2006-01-02T15:04:05.000Z"
t, err := time.Parse(layout, fmt.Sprint(target["date"]))
if err != nil {
fmt.Println(err)
}*/
if v, found := target["date"]; found {
fmt.Println(v)
str := fmt.Sprint(v)
fmt.Println(str[11:13])
}
for key := range target {
if _, ok := ref[key]; ok {
ref[key] = append(ref[key], target[key])
} else {
ref[key] = make([]interface{}, 0)
ref[key] = append(ref[key], target[key])
}
}
}
// aggregateJSONS 返回一个包含所有聚合 json 的 JSONAggregation
// 前提是提供了一个字符串格式的 json 数组
func aggregateJSONS(jsons []string) JSONAggregation {
aggregation := make(JSONAggregation, 0)
for _, result := range jsons {
aggregateInterfaces(&aggregation, JSONtoMap(result))
}
return aggregation
}
func main() {
jsons := []string{
`{
"name":"kate",
"date":"2012-04-23T18:24:59.511Z",
"data":"is nice"
}`,
`{
"name":"gleison",
"date":"2012-04-23T18:25:00.511Z",
"data":"is a good person"
}`,
`{
"name":"breno",
"date":"2012-04-23T19:25:01.511Z",
"data":"is a cool person"
}`,
}
fmt.Println(aggregateJSONS(jsons))
}
最后我得到了: 2012-04-23T18:24:59.511Z 18 2012-04-23T18:25:00.511Z 18 2012-04-23T19:25:01.511Z 19 map[data:[is nice is a good person is a cool person] date:[2012-04-23T18:24:59.511Z 2012-04-23T18:25:00.511Z 2012-04-23T19:25:01.511Z] name:[kate gleison breno]]
我的问题是:如何访问 “date” 字段。我需要做的是:按小时、天、周和月将它们分组聚合。对它们进行分类然后聚合。如何比较日期?
更多关于Golang应用程序开发遇到问题求助的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang应用程序开发遇到问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你的代码已经能够正确提取日期字符串并获取小时部分。要实现按时间分组聚合,需要解析日期字符串并进行比较。以下是修改后的代码示例:
package main
import (
"encoding/json"
"fmt"
"time"
)
// JSONMap 是 map 的特化类型
type JSONMap = map[string]interface{}
// JSONAggregation 是 map 的特化类型
type JSONAggregation = map[string][]interface{}
// JSONtoMap 将 json 字符串转换为与 Go 兼容的 JSONMap
func JSONtoMap(originalJSON string) JSONMap {
var result map[string]interface{}
json.Unmarshal([]byte(originalJSON), &result)
return result
}
// parseDate 解析日期字符串
func parseDate(dateStr string) (time.Time, error) {
layouts := []string{
time.RFC3339,
"2006-01-02T15:04:05.000Z",
"2006-01-02 15:04:05",
}
for _, layout := range layouts {
t, err := time.Parse(layout, dateStr)
if err == nil {
return t, nil
}
}
return time.Time{}, fmt.Errorf("无法解析日期: %s", dateStr)
}
// getTimeKey 根据分组类型获取时间键
func getTimeKey(t time.Time, groupBy string) string {
switch groupBy {
case "hour":
return t.Format("2006-01-02 15")
case "day":
return t.Format("2006-01-02")
case "week":
year, week := t.ISOWeek()
return fmt.Sprintf("%d-W%02d", year, week)
case "month":
return t.Format("2006-01")
default:
return t.Format("2006-01-02")
}
}
// aggregateByTime 按时间分组聚合
func aggregateByTime(jsons []string, groupBy string) map[string]JSONAggregation {
groupedData := make(map[string]JSONAggregation)
for _, jsonStr := range jsons {
data := JSONtoMap(jsonStr)
if dateVal, found := data["date"]; found {
dateStr := fmt.Sprint(dateVal)
t, err := parseDate(dateStr)
if err != nil {
fmt.Printf("解析日期错误: %v\n", err)
continue
}
timeKey := getTimeKey(t, groupBy)
if _, exists := groupedData[timeKey]; !exists {
groupedData[timeKey] = make(JSONAggregation)
}
// 聚合数据
for key, value := range data {
if key == "date" {
// 保留原始日期字符串
groupedData[timeKey][key] = append(groupedData[timeKey][key], dateStr)
} else {
groupedData[timeKey][key] = append(groupedData[timeKey][key], value)
}
}
}
}
return groupedData
}
func main() {
jsons := []string{
`{
"name":"kate",
"date":"2012-04-23T18:24:59.511Z",
"data":"is nice"
}`,
`{
"name":"gleison",
"date":"2012-04-23T18:25:00.511Z",
"data":"is a good person"
}`,
`{
"name":"breno",
"date":"2012-04-23T19:25:01.511Z",
"data":"is a cool person"
}`,
`{
"name":"alice",
"date":"2012-04-24T10:30:00.000Z",
"data":"is awesome"
}`,
}
// 按小时分组
fmt.Println("按小时分组:")
hourlyGroups := aggregateByTime(jsons, "hour")
for hour, data := range hourlyGroups {
fmt.Printf("小时 %s:\n", hour)
fmt.Printf(" names: %v\n", data["name"])
fmt.Printf(" dates: %v\n", data["date"])
fmt.Printf(" data: %v\n\n", data["data"])
}
// 按天分组
fmt.Println("\n按天分组:")
dailyGroups := aggregateByTime(jsons, "day")
for day, data := range dailyGroups {
fmt.Printf("日期 %s:\n", day)
fmt.Printf(" names: %v\n", data["name"])
fmt.Printf(" dates: %v\n", data["date"])
fmt.Printf(" data: %v\n\n", data["data"])
}
// 按月分组
fmt.Println("\n按月分组:")
monthlyGroups := aggregateByTime(jsons, "month")
for month, data := range monthlyGroups {
fmt.Printf("月份 %s:\n", month)
fmt.Printf(" names: %v\n", data["name"])
fmt.Printf(" dates: %v\n", data["date"])
fmt.Printf(" data: %v\n\n", data["data"])
}
}
这段代码添加了以下功能:
parseDate函数:使用多种格式尝试解析日期字符串getTimeKey函数:根据分组类型(hour/day/week/month)生成时间键aggregateByTime函数:按指定时间维度进行分组聚合
输出示例:
按小时分组:
小时 2012-04-23 18:
names: [kate gleison]
dates: [2012-04-23T18:24:59.511Z 2012-04-23T18:25:00.511Z]
data: [is nice is a good person]
小时 2012-04-23 19:
names: [breno]
dates: [2012-04-23T19:25:01.511Z]
data: [is a cool person]
小时 2012-04-24 10:
names: [alice]
dates: [2012-04-24T10:30:00.000Z]
data: [is awesome]
要比较日期,可以直接使用 time.Time 类型的方法:
// 比较两个日期是否在同一天
func isSameDay(t1, t2 time.Time) bool {
y1, m1, d1 := t1.Date()
y2, m2, d2 := t2.Date()
return y1 == y2 && m1 == m2 && d1 == d2
}
// 比较两个日期是否在同一小时
func isSameHour(t1, t2 time.Time) bool {
return t1.Truncate(time.Hour).Equal(t2.Truncate(time.Hour))
}
// 获取日期的开始时间(00:00:00)
func startOfDay(t time.Time) time.Time {
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
}
// 获取月份的开始时间
func startOfMonth(t time.Time) time.Time {
return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
}

