Go--较复杂的结构类型

一、List

List是一种有序的集合,可以包含任意数量的元素。与数组相比,list的长度可以动态调整,可以随时添加或删除元素,类似于切片

在go中,List是一个双向链表的实现。

实例
package main

import (
    "container/list"
    "fmt"
)

type User struct {
    id   int
    name string
}

func main() {
    l := list.New() //创建一个list
    l.PushBack(1)   //插入链表的最后一个位置
    l.PushBack(2)
    l.PushBack(3)
    l.PushFront(4)             //插入链表的第一个位置
    l.Remove(l.Front().Next()) //删除最后一个元素
    i := 1
    for e := l.Front(); e != nil; e = e.Next() {
        fmt.Printf("元素%d:%d\n", i, e.Value)
        i++
    }

    //当list中元素为struct时
    ll := list.New()
    item1 := User{id: 101, name: "name1"}
    item2 := User{id: 102, name: "name2"}
    ll.PushBack(item1)
    ll.PushBack(item2)
    a := 1
    for e := ll.Front(); e != nil; e = e.Next() {
        fmt.Printf("元素%d: id:%d, name:%s\n", a, e.Value.(User).id, e.Value.(User).name) //先转义后使用
        a++
    }
}

输出结果:

元素1:4
元素2:2
元素3:3
元素1: id:101, name:name1
元素2: id:102, name:name2
1.2 计算list相同元素的次数

 

func countOccurrences(list [][]string) map[string]map[string]int {
    occurrences := make(map[string]map[string]int)

    for _, pair := range list {
        first := pair[0]
        second := pair[1]

        if _, ok := occurrences[first]; !ok {
            occurrences[first] = make(map[string]int)
        }

        occurrences[first][second]++
    }

    return occurrences
}

 

 

二、struct类型的切片

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    id   int
    name string
}

type notifyParams struct {
    Type   string   `json:"type"`
    Values []string `json:"values"`
}

func main() {
    //实例化一个空切片
    var al []interface{}  //或者使用: al := make([]interface{}, 0)
    al = append(al, "t1") //使用append添加元素
    al = append(al, 1)
    al = append(al, "2")
    fmt.Println(al)

    //在struct中使用时
    aSlice := make([]User, 0)                            //创建一个结构体切片
    aSlice = append(aSlice, User{id: 555, name: "wang"}) //向切片中添加结构体元素
    aSlice = append(aSlice, User{id: 444, name: "wan"})
    fmt.Println(aSlice)
    for k, v := range aSlice { //遍历
        fmt.Println(k, v)
    }

    notifySlice := make([]notifyParams, 0)
    var arrs notifyParams
    arrs.Type = "test"
    arrs.Values = append(arrs.Values, "t1")
    arrs.Values = append(arrs.Values, "t2")
    arrs.Values = append(arrs.Values, "t3")
    notifySlice = append(notifySlice, arrs) //将结构体对象添加到切片中
    fmt.Println(notifySlice)
    s1, _ := json.Marshal(notifySlice) //序列化,变成json格式
    fmt.Println(string(s1))
}

输出结果

[t1 1 2]
[{555 wang} {444 wan}]
0 {555 wang}
1 {444 wan}
[{test [t1 t2 t3]}]
[{"type":"test","values":["t1","t2","t3"]}]
 2.1 统计struct里每个元素重复的次数
package main

import (
    "fmt"
    "strings"
)

// Alert 定义一个结构体类型
type Alert struct {
    Product    string
    SolverID   string
    IP         string
    PolicyName string
}

func main() {
    // 创建一个包含结构体元素的切片
    alerts := []Alert{
        {"ProductA", "Solver1", "192.168.1.1", "Policy1"},
        {"ProductB", "Solver2", "192.168.1.2", "Policy2"},
        {"ProductA", "Solver1", "192.168.1.1", "Policy3"},
        {"ProductA", "Solver3", "192.168.1.3", "Policy1"},
        {"ProductB", "Solver2", "192.168.1.2", "Policy4"},
        {"ProductA", "Solver1", "192.168.1.1", "Policy5"},
    }

    // 创建一个map来统计IP相同的次数
    ipCount := make(map[string]int)

    // 创建一个map来统计IP后面的告警策略名及其次数
    ipPolicyCount := make(map[string]map[string]int)

    // 创建一个map来存储IP对应的product和solverId
    ipProductSolverMap := make(map[string]struct {
        Product  string
        SolverID string
    })

    // 遍历切片并进行统计
    for _, alert := range alerts {
        // 统计IP相同的次数
        ipCount[alert.IP]++

        // 统计IP后面的告警策略名及其次数
        if _, ok := ipPolicyCount[alert.IP]; !ok {
            ipPolicyCount[alert.IP] = make(map[string]int)
        }
        ipPolicyCount[alert.IP][alert.PolicyName]++

        // 存储IP对应的product和solverId
        ipProductSolverMap[alert.IP] = struct {
            Product  string
            SolverID string
        }{alert.Product, alert.SolverID}
    }

    // 将结果格式化成字符串并输出
    var resultStrings []string
    for ip, count := range ipCount {
        if count > 3 {
            line := fmt.Sprintf("Product: %s SolverID: %s IP: %s (重复次数: %d) 策略名称及次数: ", ipProductSolverMap[ip].Product, ipProductSolverMap[ip].SolverID, ip, count)
            for policyName, policyCount := range ipPolicyCount[ip] {
                line += fmt.Sprintf("%s(%d), ", policyName, policyCount)
            }
            line = strings.TrimSuffix(line, ", ") // 去掉末尾的逗号和空格
            resultStrings = append(resultStrings, line)
        }
    }

    // 输出结果字符串
    for _, result := range resultStrings {
        fmt.Println(result)
    }
}

输出结果:

Product: ProductA SolverID: Solver1 IP: 192.168.1.1 (重复次数: 3) 策略名称及次数: Policy1(1), Policy3(1), Policy5(1)

 

三、补充

3.1 统计告警策略名称出现天数达3天以上的数据

查询到的告警数据结构如下:

type AlarmStr struct {
    notifydate      string
    product         string
    solverId        string
    monitorItemName string
    newestContent   string
    hasProblem      int
}

要求将相同告警策略名称的告警天数达3天以上的数据展示出来,示例代码如下:

package main

import "fmt"

type AlarmStr struct {
    notifyDate      string
    product         string
    solverId        string
    monitorItemName string
    newestContent   string
    hasProblem      int
}

func main() {
    // 定义结构体切片
    var alarms []AlarmStr

    // 赋值
    alarms = append(alarms, AlarmStr{
        notifyDate:      "2024-04-30",
        product:         "ProductA",
        solverId:        "Solver1",
        monitorItemName: "MonitorItem1",
        newestContent:   "Content1",
        hasProblem:      1,
    })

    alarms = append(alarms, AlarmStr{
        notifyDate:      "2024-04-29",
        product:         "ProductB",
        solverId:        "Solver2",
        monitorItemName: "MonitorItem2",
        newestContent:   "Content2",
        hasProblem:      0,
    })

    alarms = append(alarms, AlarmStr{
        notifyDate:      "2024-04-28",
        product:         "ProductC",
        solverId:        "Solver3",
        monitorItemName: "MonitorItem1",
        newestContent:   "Content3",
        hasProblem:      1,
    })

    alarms = append(alarms, AlarmStr{
        notifyDate:      "2024-04-29",
        product:         "ProductD",
        solverId:        "Solver4",
        monitorItemName: "MonitorItem1",
        newestContent:   "Content4",
        hasProblem:      1,
    })

    //创建映射记录具有相同 monitorItemName 值的结构体切片
    monitorItemNameData := make(map[string][]AlarmStr)

    // 遍历结构体切片,将具有相同 monitorItemName 值的结构体添加到映射中
    for _, data := range alarms {
        monitorItemNameData[data.monitorItemName] = append(monitorItemNameData[data.monitorItemName], data)
    }
    //此时,monitorItemNameData的键值如下:
    //map[MonitorItem1:[{2024-04-30 ProductA Solver1 MonitorItem1 Content1 1} {2024-04-28 ProductC Solver3 MonitorItem1 Content3 1} {2024-04-29 ProductD Solver4 MonitorItem1 Content4 1}] MonitorItem2:[{2024-04-29 ProductB Solver2 MonitorItem2 Content2 0}]]

    //遍历map,找出不同notifyDate不同值大于等于3的数据
    for _, monitorItemNameValue := range monitorItemNameData {
        // 创建 map 统计notifyTime不同值的数量,需在for循环里面创建,每次循环重置变量,不然键值会一直累加
        valueCount := make(map[string]int)

        //遍历map键值
        for _, value := range monitorItemNameValue {
            valueCount[value.notifyDate]++ //相同notifyDate值,map键值+1,不同notifyTime值,会新创建一个键值,如:[2024-04-30:1]
        }

        //判断valueCount的键值对数量,其数量就代表了notifyDate不同值的数量,大于3时输出数据
        if len(valueCount) >= 3 {
            fmt.Println(monitorItemNameValue)
        }
    }

}

输出如下,可看出 MonitorItem1 确实是3天都有告警

[{2024-04-30 ProductA Solver1 MonitorItem1 Content1 1} {2024-04-28 ProductC Solver3 MonitorItem1 Content3 1} {2024-04-29 ProductD Solver4 MonitorItem1 Content4 1}]

 

posted @ 2023-08-30 16:28  心恩惠动  阅读(12)  评论(0编辑  收藏  举报