W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
緩存組件默認(rèn)提供了一個(gè)高速的內(nèi)存緩存,操作效率非常高效,?CPU
?性能損耗在?ns
?納秒級(jí)別。
package main
import (
"fmt"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
)
func main() {
// 創(chuàng)建一個(gè)緩存對(duì)象,
// 當(dāng)然也可以便捷地直接使用gcache包方法
var (
ctx = gctx.New()
cache = gcache.New()
)
// 設(shè)置緩存,不過(guò)期
err := cache.Set(ctx, "k1", "v1", 0)
if err != nil {
panic(err)
}
// 獲取緩存值
value, err := cache.Get(ctx, "k1")
if err != nil {
panic(err)
}
fmt.Println(value)
// 獲取緩存大小
size, err := cache.Size(ctx)
if err != nil {
panic(err)
}
fmt.Println(size)
// 緩存中是否存在指定鍵名
b, err := cache.Contains(ctx, "k1")
if err != nil {
panic(err)
}
fmt.Println(b)
// 刪除并返回被刪除的鍵值
removedValue, err := cache.Remove(ctx, "k1")
if err != nil {
panic(err)
}
fmt.Println(removedValue)
// 關(guān)閉緩存對(duì)象,讓GC回收資源
if err = cache.Close(ctx); err != nil {
panic(err)
}
}
執(zhí)行后,輸出結(jié)果為:
v1
1
true
v1
package main
import (
"fmt"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
"time"
)
func main() {
var (
ctx = gctx.New()
)
// 當(dāng)鍵名不存在時(shí)寫入,設(shè)置過(guò)期時(shí)間1000毫秒
_, err := gcache.SetIfNotExist(ctx, "k1", "v1", time.Second)
if err != nil {
panic(err)
}
// 打印當(dāng)前的鍵名列表
keys, err := gcache.Keys(ctx)
if err != nil {
panic(err)
}
fmt.Println(keys)
// 打印當(dāng)前的鍵值列表
values, err := gcache.Values(ctx)
if err != nil {
panic(err)
}
fmt.Println(values)
// 獲取指定鍵值,如果不存在時(shí)寫入,并返回鍵值
value, err := gcache.GetOrSet(ctx, "k2", "v2", 0)
if err != nil {
panic(err)
}
fmt.Println(value)
// 打印當(dāng)前的鍵值對(duì)
data1, err := gcache.Data(ctx)
if err != nil {
panic(err)
}
fmt.Println(data1)
// 等待1秒,以便k1:v1自動(dòng)過(guò)期
time.Sleep(time.Second)
// 再次打印當(dāng)前的鍵值對(duì),發(fā)現(xiàn)k1:v1已經(jīng)過(guò)期,只剩下k2:v2
data2, err := gcache.Data(ctx)
if err != nil {
panic(err)
}
fmt.Println(data2)
}
執(zhí)行后,輸出結(jié)果為:
[k1]
[v1]
v2
map[k1:v1 k2:v2]
map[k2:v2]
?GetOrSetFunc
?獲取一個(gè)緩存值,當(dāng)緩存不存在時(shí)執(zhí)行指定的?f func() (interface{}, error)
?,緩存該?f
?方法的結(jié)果值,并返回該結(jié)果。
需要注意的是,?GetOrSetFunc
?的緩存方法參數(shù)?f
?是在緩存的鎖機(jī)制外執(zhí)行,因此在?f
?內(nèi)部也可以嵌套調(diào)用?GetOrSetFunc
?。但如果?f
?的執(zhí)行比較耗時(shí),高并發(fā)的時(shí)候容易出現(xiàn)?f
?被多次執(zhí)行的情況(緩存設(shè)置只有第一個(gè)執(zhí)行的?f
?返回結(jié)果能夠設(shè)置成功,其余的被拋棄掉)。而?GetOrSetFuncLock
?的緩存方法?f
?是在緩存的鎖機(jī)制內(nèi)執(zhí)行,因此可以保證當(dāng)緩存項(xiàng)不存在時(shí)只會(huì)執(zhí)行一次?f
?,但是緩存寫鎖的時(shí)間隨著?f
?方法的執(zhí)行時(shí)間而定。
我們來(lái)看一個(gè)示例:
package main
import (
"fmt"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
"time"
)
func main() {
var (
ch = make(chan struct{}, 0)
ctx = gctx.New()
key = `key`
value = `value`
)
for i := 0; i < 10; i++ {
go func(index int) {
<-ch
_, err := gcache.GetOrSetFuncLock(ctx, key, func() (interface{}, error) {
fmt.Println(index, "entered")
return value, nil
}, 0)
if err != nil {
panic(err)
}
}(i)
}
close(ch)
time.Sleep(time.Second)
}
執(zhí)行后,終端輸出(帶有隨機(jī)性,但是只會(huì)輸出一條信息):
9 entered
可以看到,多個(gè)?goroutine
?同時(shí)調(diào)用?GetOrSetFuncLock
?方法時(shí),由于該方法有并發(fā)安全控制,因此最終只有一個(gè)?goroutine
?的數(shù)值生成函數(shù)執(zhí)行成功,成功之后其他?goroutine
?拿到數(shù)據(jù)后則立即返回不再執(zhí)行對(duì)應(yīng)的數(shù)值生成函數(shù)。
package main
import (
"fmt"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
"time"
)
func main() {
var (
ctx = gctx.New()
cache = gcache.New(2) // 設(shè)置LRU淘汰數(shù)量
)
// 添加10個(gè)元素,不過(guò)期
for i := 0; i < 10; i++ {
if err := cache.Set(ctx, i, i, 0); err != nil {
panic(err)
}
}
size, err := cache.Size(ctx)
if err != nil {
panic(err)
}
fmt.Println(size)
keys, err := cache.Keys(ctx)
if err != nil {
panic(err)
}
fmt.Println(keys)
// 讀取鍵名1,保證該鍵名是優(yōu)先保留
value, err := cache.Get(ctx, 1)
if err != nil {
panic(err)
}
fmt.Println(value)
// 等待一定時(shí)間后(默認(rèn)1秒檢查一次),
// 元素會(huì)被按照從舊到新的順序進(jìn)行淘汰
time.Sleep(3 * time.Second)
size, err = cache.Size(ctx)
if err != nil {
panic(err)
}
fmt.Println(size)
keys, err = cache.Keys(ctx)
if err != nil {
panic(err)
}
fmt.Println(keys)
}
執(zhí)行后,輸出結(jié)果為:
10
[2 3 5 6 7 0 1 4 8 9]
1
2
[1 9]
CPU: Intel(R) Core(TM) i5-4460 CPU @ 3.20GHz
MEM: 8GB
SYS: Ubuntu 16.04 amd64
john@john-B85M:~/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/os/gcache$ go test *.go -bench=".*" -benchmem
goos: linux
goarch: amd64
Benchmark_CacheSet-4 2000000 897 ns/op 249 B/op 4 allocs/op
Benchmark_CacheGet-4 5000000 202 ns/op 49 B/op 1 allocs/op
Benchmark_CacheRemove-4 50000000 35.7 ns/op 0 B/op 0 allocs/op
Benchmark_CacheLruSet-4 2000000 880 ns/op 399 B/op 4 allocs/op
Benchmark_CacheLruGet-4 3000000 212 ns/op 33 B/op 1 allocs/op
Benchmark_CacheLruRemove-4 50000000 35.9 ns/op 0 B/op 0 allocs/op
Benchmark_InterfaceMapWithLockSet-4 3000000 477 ns/op 73 B/op 2 allocs/op
Benchmark_InterfaceMapWithLockGet-4 10000000 149 ns/op 0 B/op 0 allocs/op
Benchmark_InterfaceMapWithLockRemove-4 50000000 39.8 ns/op 0 B/op 0 allocs/op
Benchmark_IntMapWithLockWithLockSet-4 5000000 304 ns/op 53 B/op 0 allocs/op
Benchmark_IntMapWithLockGet-4 20000000 164 ns/op 0 B/op 0 allocs/op
Benchmark_IntMapWithLockRemove-4 50000000 33.1 ns/op 0 B/op 0 allocs/op
PASS
ok command-line-arguments 47.503s
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: