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