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"])
    }
}

这段代码添加了以下功能:

  1. parseDate 函数:使用多种格式尝试解析日期字符串
  2. getTimeKey 函数:根据分组类型(hour/day/week/month)生成时间键
  3. 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())
}
回到顶部