实现自定义排序
package main
import (
"sort"
"time"
)
type Data struct {
Info struct {
SubInfo1 int
SubInfo2 string
}
Time time.Time
}
type ByTimeAndSubInfo1 []Data
func (a ByTimeAndSubInfo1) Len() int { return len(a) }
func (a ByTimeAndSubInfo1) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByTimeAndSubInfo1) Less(i, j int) bool {
if a[i].Time.Equal(a[j].Time) {
return a[i].Info.SubInfo1 > a[j].Info.SubInfo1
}
return a[i].Time.Before(a[j].Time)
}
func main() {
var dataSlice []Data
// 填充数据
sort.Sort(ByTimeAndSubInfo1(dataSlice))
}
性能优化点
- 减少比较次数:在
Less
方法中,通过先比较 Time
字段,只有在 Time
字段相等时才比较 Info.SubInfo1
,减少不必要的比较。
- 避免不必要的内存分配:尽量在已有数据结构上进行操作,避免在排序过程中频繁分配新的内存。
并发安全问题及解决方案
- 并发安全问题:当该切片在多协程中读写时,可能会出现数据竞争。例如,一个协程在读取切片数据时,另一个协程可能正在对切片进行排序或修改数据,导致读取到不一致的数据。
- 解决方案:
- 互斥锁(Mutex):使用
sync.Mutex
来保护对切片的读写操作。在读取或修改切片前,先获取锁,操作完成后释放锁。
var mu sync.Mutex
var dataSlice []Data
func readData() {
mu.Lock()
defer mu.Unlock()
// 读取 dataSlice 操作
}
func writeData() {
mu.Lock()
defer mu.Unlock()
// 修改 dataSlice 操作,如排序
}
- 读写锁(RWMutex):如果读操作远多于写操作,可以使用
sync.RWMutex
。读操作时获取读锁,写操作时获取写锁。读锁可以被多个读操作同时持有,而写锁会排斥其他读锁和写锁。
var rwmu sync.RWMutex
var dataSlice []Data
func readData() {
rwmu.RLock()
defer rwmu.RUnlock()
// 读取 dataSlice 操作
}
func writeData() {
rwmu.Lock()
defer rwmu.Unlock()
// 修改 dataSlice 操作,如排序
}