在go语言种使用泛型实现一个有序map示例
Go  /  管理员 发布于 8个月前   190
在Go中,泛型的实现依赖于接口和反射。由于Go不是一种泛型编程语言,所以它没有内置的泛型机制。
但是,我们可以通过定义一个泛型接口和使用反射来实现类似泛型的行为。
以下是一个简单的有序Map实现的例子,
它使用了接口和反射来实现泛型特性:
package main
import (
"fmt"
"reflect"
"sort"
)
// KeyType 定义了可以作为键的类型
type KeyType interface{}
// Item 是map中的一个键值对
type Item struct {
Key KeyType
Value interface{}
}
// By 用于排序的关键字
type By []Item
func (a By) Len() int { return len(a) }
func (a By) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a By) Less(i, j int) bool { return a[i].Key.(int) < a[j].Key.(int) }
// OrderedMap 是一个有序的map结构
type OrderedMap struct {
items []Item
}
// Set 添加或更新键值对
func (m *OrderedMap) Set(key KeyType, value interface{}) {
for i, item := range m.items {
if eq(item.Key, key) {
m.items[i].Value = value
return
}
}
m.items = append(m.items, Item{key, value})
}
// Get 获取键对应的值
func (m *OrderedMap) Get(key KeyType) interface{} {
for _, item := range m.items {
if eq(item.Key, key) {
return item.Value
}
}
return nil
}
// eq 检查两个值是否相等
func eq(a, b KeyType) bool {
return reflect.DeepEqual(a, b)
}
func main() {
// 创建一个OrderedMap实例
om := &OrderedMap{}
// 添加键值对
om.Set(1, "one")
om.Set(2, "two")
om.Set(3, "three")
// 根据键获取值
fmt.Println(om.Get(2)) // 输出: two
// 对键进行排序
sort.Stable(By(om.items))
// 打印排序后的键值对
for _, item := range om.items {
fmt.Printf("Key: %v, Value: %v\n", item.Key, item.Value)
}
// 输出:
// Key: 1, Value: one
// Key: 2, Value: two
// Key: 3, Value: three
}
ps:
这个例子中,OrderedMap 结构体包含一个 Item 类型的切片,代表有序的键值对集合。
Set 方法用于添加或更新键值对,Get 方法用于获取特定键对应的值。
eq 函数用于比较两个键是否相等,By 类型实现了 sort.Interface 接口,允许我们根据键对集合进行排序。
这个实现虽然功能完善,但是因为使用了反射和interface{},可能会牺牲一定的性能。
第二种:基于泛型实现一个有序map示例,有兴趣可自行测试
package main
import (
"fmt"
"sort"
"sync"
)
type OrderedMap[K comparable, V any] struct {
keys []K
values map[K]V
mutex sync.RWMutex
less func(K, K) bool
}
func NewOrderedMap[K comparable, V any](less func(K, K) bool) *OrderedMap[K, V] {
return &OrderedMap[K, V]{
keys: make([]K, 0),
values: make(map[K]V),
less: less,
}
}
func (om *OrderedMap[K, V]) Set(key K, value V) {
om.mutex.Lock()
defer om.mutex.Unlock()
if _, exists := om.values[key]; !exists {
om.keys = append(om.keys, key)
sort.Slice(om.keys, func(i, j int) bool {
return om.less(om.keys[i], om.keys[j])
})
}
om.values[key] = value
}
func (om *OrderedMap[K, V]) Get(key K) (V, bool) {
om.mutex.RLock()
defer om.mutex.RUnlock()
value, exists := om.values[key]
return value, exists
}
func (om *OrderedMap[K, V]) Keys() []K {
om.mutex.RLock()
defer om.mutex.RUnlock()
return om.keys
}
func (om *OrderedMap[K, V]) Range(f func(key K, value V) bool) {
om.mutex.RLock()
defer om.mutex.RUnlock()
for _, key := range om.keys {
value, exists := om.values[key]
if !exists {
continue
}
if !f(key, value) {
break
}
}
}
func main() {
om := NewOrderedMap[int, int](func(a, b int) bool {
return a < b
})
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
om.Set(4, 2)
om.Set(5, 1)
}()
go func() {
defer wg.Done()
om.Set(9, 3)
om.Set(7, 4)
}()
wg.Wait()
//fmt.Println("Keys in order:")
//for _, key := range om.Keys() {
// value, _ := om.Get(key)
// fmt.Printf("%v: %v\n", key, value)
//}
fmt.Println("Keys in order:")
om.Range(func(key int, value int) bool {
fmt.Printf("%v: %v\n", key, value)
return true
})
}
123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..路人 在
php中使用hyperf框架调用讯飞星火大模型实现国内版chatgpt功能示例中评论 教程很详细,如果加个前端chatgpt对话页面就完美了..Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号