網(wǎng)站首頁 編程語言 正文
正文
cache 是一個(gè)帶索引帶超時(shí)的緩存庫
目的在于優(yōu)化代碼結(jié)構(gòu),提供了若干實(shí)踐。?https://github.com/weapons97/cache
example
定義泛型函數(shù)
1.18 已經(jīng)發(fā)布一段實(shí)踐了。通過泛型函數(shù)。我們可以減少循環(huán)的使用,優(yōu)化代碼結(jié)構(gòu)。下面分享幾個(gè)泛型函數(shù)和代碼上的實(shí)踐。
Filter 函數(shù)
// Filter filter one slice func Filter[T any](objs []T, filter func(obj T) bool) []T { res := make([]T, 0, len(objs)) for i := range objs { ok := filter(objs[i]) if ok { res = append(res, objs[i]) } } return res }
// 測試[]int func TestFilter(t *testing.T) { ans := []int{2, 4, 6} a := []int{1, 2, 3, 4, 5, 6} b := Filter(a, func(i int) bool { return i%2 == 0 }) require.Equal(t, ans, b) spew.Dump(b) } // 結(jié)果 === RUN TestFilter ([]int) (len=3 cap=6) { (int) 2, (int) 4, (int) 6 } --- PASS: TestFilter (0.00s) PASS // NoSpace is filter func for strings func NoSpace(s string) bool { return strings.TrimSpace(s) != "" } // 測試[]sting func TestFilterNoSpace(t *testing.T) { ans1 := []string{"1", "2", "3"} a := []string{"", "1", "", "2", "", "3", ""} b := Filter(a, NoSpace) require.Equal(t, ans1, b) spew.Dump(b) } // 結(jié)果 === RUN TestFilterNoSpace ([]string) (len=3 cap=7) { (string) (len=1) "1", (string) (len=1) "2", (string) (len=1) "3" } --- PASS: TestFilterNoSpace (0.00s) PASS
Map 函數(shù)
// Map one slice func Map[T any, K any](objs []T, mapper func(obj T) ([]K, bool)) []K { res := make([]K, 0, len(objs)) for i := range objs { others, ok := mapper(objs[i]) if ok { res = append(res, others...) } } return res } // 測試 []int -> []string func TestMap(t *testing.T) { ans := []string{"2", "4", "6", "end"} a := []int{1, 2, 3, 4, 5, 6} b := Map(a, func(i int) ([]string, bool) { if i == 6 { return []string{fmt.Sprintf(`%v`, i), `end`}, true } if i%2 == 0 { return []string{fmt.Sprintf(`%v`, i)}, true } else { return nil, false } }) require.Equal(t, ans, b) spew.Dump(b) } // 結(jié)果 === RUN TestMap ([]string) (len=4 cap=6) { (string) (len=1) "2", (string) (len=1) "4", (string) (len=1) "6", (string) (len=3) "end" } --- PASS: TestMap (0.00s) PASS
First 函數(shù)
// First make return first for slice func First[T any](objs []T) (T, bool) { if len(objs) > 0 { return objs[0], true } return *new(T), false } func TestFirstInt(t *testing.T) { ans1, ans2 := 1, 0 a := []int{1, 2, 3, 4, 5, 6} b, ok := First(a) require.True(t, ok) require.Equal(t, ans1, b) spew.Dump(b) c := []int{} d, ok := First(c) require.False(t, ok) require.Equal(t, ans2, d) spew.Dump(d) } // result === RUN TestFirstInt (int) 1 (int) 0 --- PASS: TestFirstInt (0.00s) PASS func TestFirstString(t *testing.T) { ans1, ans2 := "1", "" a := []string{"1", "2", "3", "4", "5", "6"} b, ok := First(a) require.True(t, ok) require.Equal(t, ans1, b) spew.Dump(b) c := []string{} d, ok := First(c) require.False(t, ok) require.Equal(t, ans2, d) spew.Dump(d) } // result === RUN TestFirstString (string) (len=1) "1" (string) "" --- PASS: TestFirstString (0.00s) PASS
帶超時(shí)的cache
- 某些情況下,我們刪除過期的cache, 通過利用帶超時(shí)的cache,簡化代碼
cache 結(jié)構(gòu)
// 用輔助map刪除 if apiRet.TotalCount > 0 { var hc sync.Map for _, h := range apiRet.Hcis { hc.Store(h.HostID, h) hostCpu.Store(h.HostID, h) } hostCpu.Range(func(key, _ interface{}) bool { _, ok := hc.Load(key) if !ok { hostCpu.Delete(key) } return true }) } // 直接設(shè)置,過期的key 會刪除 for _, h := range apiRet.Hcis { hostCpu.Set(h.HostID, h) }
func TestNewCache(t *testing.T) { c := NewCache(WithTTL[string, int](time.Second)) b := 1 c.Set(`a`, b) d, ok := c.Get(`a`) require.True(t, ok) require.Equal(t, b, d) time.Sleep(time.Second) d, ok = c.Get(`a`) require.False(t, ok) // 超時(shí)返回0值 require.Equal(t, d, 0) }
集合操作
通過 set 做集合,可以給集合去重。可以給結(jié)合相并,想交,等操作。
set 結(jié)構(gòu)
func TestSetUnion(t *testing.T) { s := NewSet[string]() s.Add(`a`) s.Add(`b`) s2 := NewSet[string]() s2.Add(`b`) s2.Add(`d`) s3 := s.Union(s2) wantS3 := []string{`a`, `b`, `d`} ans := s3.List() sort.Strings(ans) require.Equal(t, wantS3, ans) spew.Dump(s.List(), s2.List(), s3.List()) } func TestSetJoin(t *testing.T) { s := NewSet[string]() s.Add(`a`) s.Add(`b`) s2 := NewSet[string]() s2.Add(`b`) s2.Add(`d`) s3 := s.Join(s2) wantS3 := []string{`b`} ans := s3.List() sort.Strings(ans) require.Equal(t, wantS3, ans) spew.Dump(s.List(), s2.List(), s3.List()) } func TestSetJoinLeft(t *testing.T) { s := NewSet[string]() s.Add(`a`) s.Add(`b`) s2 := NewSet[string]() s2.Add(`b`) s2.Add(`d`) s3 := s.JoinLeft(s2) wantS3 := []string{`a`, `b`} ans := s3.List() sort.Strings(ans) require.Equal(t, wantS3, ans) spew.Dump(s.List(), s2.List(), s3.List()) } func TestSetJoinRight(t *testing.T) { s := NewSet[string]() s.Add(`a`) s.Add(`b`) s2 := NewSet[string]() s2.Add(`b`) s2.Add(`d`) s3 := s.JoinRight(s2) wantS3 := []string{`b`, `d`} ans := s3.List() sort.Strings(ans) require.Equal(t, wantS3, ans) spew.Dump(s.List(), s2.List(), s3.List()) } func TestSetSub(t *testing.T) { s := NewSet[string]() s.Add(`a`) s.Add(`b`) s2 := NewSet[string]() s2.Add(`b`) s2.Add(`d`) s3 := s.Sub(s2) wantS3 := []string{`a`} ans := s3.List() sort.Strings(ans) require.Equal(t, wantS3, ans) spew.Dump(s.List(), s2.List(), s3.List()) }
通過set 去重
// ShowImageInManifest 抓取 manifest 中imgs func ShowImageInManifest(manifest string) (imgs []string) { rx := regImages.FindAllStringSubmatch(manifest, -1) set := cache.NewSet[string]() for i := range rx { for j := range rx[i] { if strings.HasPrefix(rx[i][j], `image:`) { continue } tx0 := strings.TrimSpace(rx[i][j]) tx1 := strings.Trim(tx0, `'`) tx2 := strings.Trim(tx1, `"`) set.Add(tx2) } } imgs = set.List() return imgs }
帶索引的cache
某些情況下,我們可能根據(jù)cache 的某個(gè)元素對cache進(jìn)行遍歷,這時(shí)候如果給cache 加上索引結(jié)構(gòu),可以對遍歷加速。
index 結(jié)構(gòu)
type Person struct { id string lastName string fullName string country string } const ( IndexByLastName = `IndexByLastName` IndexByCountry = `IndexByCountry` ) func (p *Person) Indexs() map[string]IndexFunc { return map[string]IndexFunc{ IndexByLastName: func(indexed Indexed) (key []string) { ci := indexed.(*Person) return []string{ci.lastName} }, IndexByCountry: func(indexed Indexed) (key []string) { ci := indexed.(*Person) return []string{ci.country} }, } } func (p *Person) ID() (mainKey string) { return p.id } func (p *Person) Set(v interface{}) (Indexed, bool) { rx, ok := v.(*Person) if !ok { return nil, false } return rx, true } func (p *Person) Get(v Indexed) (interface{}, bool) { rx, ok := v.(*Person) if !ok { return nil, false } return rx, true }
// 測試數(shù)據(jù) var ( p1 = &Person{ id: `1`, lastName: "魏", fullName: "魏鵬", country: `China`, } p2 = &Person{ id: `2`, lastName: "魏", fullName: "魏無忌", country: `America`, } p3 = &Person{ id: `3`, lastName: "李", fullName: "李云", country: `China`, } p4 = &Person{ id: `4`, lastName: "黃", fullName: "黃帥來", country: `China`, } p5 = &Person{ id: `5`, lastName: "Cook", fullName: "TimCook", country: `America`, } p6 = &Person{ id: `6`, lastName: "Jobs", fullName: "SteveJobs", country: `America`, } p7 = &Person{ id: `7`, lastName: "Musk", fullName: "Elon Musk", country: `America`, } )
func TestIndexByCountry(t *testing.T) { index := NewIndexer(&Person{}) // set index.Set(p1) index.Set(p2) index.Set(p3) index.Set(p4) index.Set(p5) index.Set(p6) index.Set(p7) // search rs := index.Search(IndexByCountry, `China`) require.False(t, rs.Failed()) rx := rs.InvokeAll() require.Len(t, rx, 3) spew.Dump(rx) one := rs.InvokeOne().(*Person) require.Equal(t, one.country, `China`) spew.Dump(one) } // result === RUN TestIndexByCountry ([]interface {}) (len=3 cap=3) { (*cache.Person)(0x14139c0)({ id: (string) (len=1) "3", lastName: (string) (len=3) "李", fullName: (string) (len=6) "李云", country: (string) (len=5) "China" }), (*cache.Person)(0x1413a00)({ id: (string) (len=1) "4", lastName: (string) (len=3) "黃", fullName: (string) (len=9) "黃帥來", country: (string) (len=5) "China" }), (*cache.Person)(0x1413940)({ id: (string) (len=1) "1", lastName: (string) (len=3) "魏", fullName: (string) (len=6) "魏鵬", country: (string) (len=5) "China" }) } (*cache.Person)(0x14139c0)({ id: (string) (len=1) "3", lastName: (string) (len=3) "李", fullName: (string) (len=6) "李云", country: (string) (len=5) "China" }) --- PASS: TestIndexByCountry (0.00s) PASS
原文鏈接:https://studygolang.com/articles/35840
相關(guān)推薦
- 2023-01-26 Kotlin協(xié)程Channel源碼示例淺析_Android
- 2022-06-07 SQL?Server內(nèi)存機(jī)制詳解_MsSql
- 2022-05-09 python中pip安裝庫時(shí)出現(xiàn)Read?timed?out解決辦法_python
- 2023-06-18 一文帶你了解C#中的協(xié)變與逆變_C#教程
- 2022-10-15 C語言利用UDP實(shí)現(xiàn)群聊聊天室的示例代碼_C 語言
- 2022-08-29 Python可視化神器pyecharts之繪制箱形圖_python
- 2022-09-18 GO語言原生實(shí)現(xiàn)文件上傳功能_Golang
- 2021-12-19 Linux下wget命令詳細(xì)介紹_Linux
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支