Golang中如何按时间与hall_id对Session结构体切片排序?
Go Session切片多字段排序实现方案
需求说明
需要对Session类型切片按startTime和hall_id字段进行排序,原切片定义如下:
Sessions := []Session{ Session{ name: "superman", hall_id: 1, startTime: time.Date(2022, time.August, 15, 17, 35, 0, 0, time.UTC), endTime: time.Date(2022, time.August, 15, 18, 35, 0, 0, time.UTC), }, Session{ name: "thor", hall_id: 2, startTime: time.Date(2022, time.August, 15, 16, 30, 0, 0, time.UTC), endTime: time.Date(2022, time.August, 15, 17, 30, 0, 0, time.UTC), }, Session{ name: "joker", hall_id: 3, startTime: time.Date(2022, time.August, 15, 19, 40, 0, 0, time.UTC), endTime: time.Date(2022, time.August, 15, 20, 30, 0, 0, time.UTC), }, Session{ name: "batman", hall_id: 1, startTime: time.Date(2022, time.August, 15, 17, 40, 0, 0, time.UTC), endTime: time.Date(2022, time.August, 15, 18, 20, 0, 0, time.UTC), }, }
错误分析
你之前尝试的多字段排序写法存在语法错误:return语句不能用逗号分隔多个布尔条件,Go的排序比较函数必须返回单个bool值。此外,无需手动拆分time.Time的年月日时分进行比较,time.Time类型自带的Before()、Equal()等方法已经实现了完整的时间维度比较。
正确实现方法
方法一:使用sort.Slice(推荐,快速实现)
根据排序优先级编写比较逻辑:先判断高优先级字段,相等时再判断次优先级字段。
场景1:先按hall_id升序,再按startTime升序
sort.Slice(Sessions, func(i, j int) bool { // 先比较hall_id,不同则直接返回结果 if Sessions[i].hall_id != Sessions[j].hall_id { return Sessions[i].hall_id < Sessions[j].hall_id } // hall_id相同时,比较startTime return Sessions[i].startTime.Before(Sessions[j].startTime) })
场景2:先按startTime升序,再按hall_id升序
sort.Slice(Sessions, func(i, j int) bool { // 先比较startTime,不同则直接返回结果 if !Sessions[i].startTime.Equal(Sessions[j].startTime) { return Sessions[i].startTime.Before(Sessions[j].startTime) } // startTime相同时,比较hall_id return Sessions[i].hall_id < Sessions[j].hall_id })
方法二:实现sort.Interface接口(适合复用排序逻辑)
如果需要多次使用相同的排序规则,可以自定义切片类型并实现sort.Interface的三个方法:
// 定义自定义切片类型 type SessionSlice []Session // 返回切片长度 func (s SessionSlice) Len() int { return len(s) } // 交换两个元素位置 func (s SessionSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // 定义比较规则:先hall_id,后startTime func (s SessionSlice) Less(i, j int) bool { if s[i].hall_id != s[j].hall_id { return s[i].hall_id < s[j].hall_id } return s[i].startTime.Before(s[j].startTime) }
使用时直接调用sort.Sort:
sort.Sort(SessionSlice(Sessions))
排序结果示例
以场景1(先hall_id后startTime)为例,排序后的切片顺序为:
- superman(hall_id=1,startTime=17:35)
- batman(hall_id=1,startTime=17:40)
- thor(hall_id=2,startTime=16:30)
- joker(hall_id=3,startTime=19:40)
内容的提问来源于stack exchange,提问作者notajoke
相关产品推荐
相关产品推荐

