[{"data":1,"prerenderedAt":1922},["ShallowReactive",2],{"content:\u002F2025\u002F08\u002Fredis-in-golang-practice":3,"surround:\u002F2025\u002F08\u002Fredis-in-golang-practice":1911},{"id":4,"title":5,"body":6,"categories":1889,"date":1891,"description":1892,"draft":1893,"extension":1894,"image":1895,"meta":1896,"navigation":159,"path":1898,"permalink":1895,"published":1895,"readingTime":1899,"recommend":1895,"references":1895,"seo":1904,"sitemap":1905,"stem":1906,"tags":1907,"type":1909,"updated":1891,"__hash__":1910},"content\u002Fposts\u002F2025\u002F08\u002Fredis-in-golang-practice.md","Go 项目中的 Redis 缓存实践",{"type":7,"value":8,"toc":1883},"minimark",[9,13,16,19,23,304,307,310,313,374,377,507,513,516,538,541,1320,1334,1337,1864,1867,1873,1876,1879],[10,11,12],"p",{},"最近在看极客时间大明老师的极客训练营，初步了解了一下redis在golang中的使用",[10,14,15],{},"对于ddd架构来说，我们常用redis来缓存一些常用的sql查询，在缓解数据库压力的同时，能够提升效率和保护系统",[10,17,18],{},"在大明老师的课中，我改变了原有使用redis的观念，如今能写出相对之前更优雅的代码",[20,21,22],"h2",{"id":22},"初始化redis",[24,25,30],"pre",{"className":26,"code":27,"language":28,"meta":29,"style":29},"language-go shiki shiki-themes github-light github-dark","func NewRedis() *redis.Client {\n\tclient := redis.NewClient(&redis.Options{\n\t\tAddr:     \"localhost:6379\",\n\t\tPassword: \"\",\n\t})\n\n\t\u002F\u002F 校验redis连通性\n\tif _, err := client.Ping(context.Background()).Result(); err != nil {\n\t\tslog.Error(\"连接Redis失败\", \"error\", err)\n\t\tpanic(err.Error())\n\t}\n\treturn client\n}\n","go","",[31,32,33,74,109,126,141,154,161,170,226,255,278,288,299],"code",{"__ignoreMap":29},[34,35,38,42,46,50,53,57,60,63,66,69,71],"span",{"class":36,"data-line":37,"line":37},"line",1,[34,39,41],{"class":40},"szBVR","func",[34,43,45],{"class":44},"sScJk"," NewRedis",[34,47,49],{"class":48},"sSDpw","(",[34,51,52],{"class":48},")",[34,54,56],{"class":55},"sVt8B"," ",[34,58,59],{"class":40},"*",[34,61,62],{"class":44},"redis",[34,64,65],{"class":55},".",[34,67,68],{"class":44},"Client",[34,70,56],{"class":55},[34,72,73],{"class":48},"{\n",[34,75,77,81,84,87,90,93,96,99,101,103,106],{"class":36,"data-line":76,"line":76},2,[34,78,80],{"class":79},"indent","\t",[34,82,83],{"class":55},"client ",[34,85,86],{"class":40},":=",[34,88,89],{"class":55}," redis.",[34,91,92],{"class":44},"NewClient",[34,94,49],{"class":95},"sJX2D",[34,97,98],{"class":40},"&",[34,100,62],{"class":44},[34,102,65],{"class":55},[34,104,105],{"class":44},"Options",[34,107,73],{"class":108},"sqkie",[34,110,112,114,116,119,123],{"class":36,"data-line":111,"line":111},3,[34,113,80],{"class":79},[34,115,80],{"class":79},[34,117,118],{"class":55},"Addr:     ",[34,120,122],{"class":121},"sZZnC","\"localhost:6379\"",[34,124,125],{"class":55},",\n",[34,127,129,131,133,136,139],{"class":36,"data-line":128,"line":128},4,[34,130,80],{"class":79},[34,132,80],{"class":79},[34,134,135],{"class":55},"Password: ",[34,137,138],{"class":121},"\"\"",[34,140,125],{"class":55},[34,142,144,146,148,151],{"class":36,"data-line":143,"line":143},5,[34,145,80],{"class":79},[34,147,29],{"class":55},[34,149,150],{"class":108},"}",[34,152,153],{"class":95},")\n",[34,155,157],{"class":36,"data-line":156,"line":156},6,[34,158,160],{"emptyLinePlaceholder":159},true,"\n",[34,162,164,166],{"class":36,"data-line":163,"line":163},7,[34,165,80],{"class":79},[34,167,169],{"class":168},"sJ8bj","\u002F\u002F 校验redis连通性\n",[34,171,173,175,178,181,183,186,189,191,194,197,199,201,203,205,208,210,212,215,218,222,224],{"class":36,"data-line":172,"line":172},8,[34,174,80],{"class":79},[34,176,177],{"class":40},"if",[34,179,180],{"class":55}," _, err ",[34,182,86],{"class":40},[34,184,185],{"class":55}," client.",[34,187,188],{"class":44},"Ping",[34,190,49],{"class":95},[34,192,193],{"class":55},"context.",[34,195,196],{"class":44},"Background",[34,198,49],{"class":108},[34,200,52],{"class":108},[34,202,52],{"class":95},[34,204,65],{"class":55},[34,206,207],{"class":44},"Result",[34,209,49],{"class":95},[34,211,52],{"class":95},[34,213,214],{"class":55},"; err ",[34,216,217],{"class":40},"!=",[34,219,221],{"class":220},"sj4cs"," nil",[34,223,56],{"class":55},[34,225,73],{"class":95},[34,227,229,231,233,236,239,241,244,247,250,253],{"class":36,"data-line":228,"line":228},9,[34,230,80],{"class":79},[34,232,80],{"class":79},[34,234,235],{"class":55},"slog.",[34,237,238],{"class":44},"Error",[34,240,49],{"class":108},[34,242,243],{"class":121},"\"连接Redis失败\"",[34,245,246],{"class":55},", ",[34,248,249],{"class":121},"\"error\"",[34,251,252],{"class":55},", err",[34,254,153],{"class":108},[34,256,258,260,262,265,267,270,272,274,276],{"class":36,"data-line":257,"line":257},10,[34,259,80],{"class":79},[34,261,80],{"class":79},[34,263,264],{"class":44},"panic",[34,266,49],{"class":108},[34,268,269],{"class":55},"err.",[34,271,238],{"class":44},[34,273,49],{"class":48},[34,275,52],{"class":48},[34,277,153],{"class":108},[34,279,281,283,285],{"class":36,"data-line":280,"line":280},11,[34,282,80],{"class":79},[34,284,29],{"class":55},[34,286,287],{"class":95},"}\n",[34,289,291,293,296],{"class":36,"data-line":290,"line":290},12,[34,292,80],{"class":79},[34,294,295],{"class":40},"return",[34,297,298],{"class":55}," client\n",[34,300,302],{"class":36,"data-line":301,"line":301},13,[34,303,287],{"class":48},[10,305,306],{},"我们一般在基础设施层【infra】去初始化redis示例",[20,308,309],{"id":309},"注入repo层",[10,311,312],{},"目录结构",[24,314,318],{"className":315,"code":316,"language":317,"meta":29,"style":29},"language-bash shiki shiki-themes github-light github-dark","root@pzj:\u002Fcode\u002Fprogram\u002FAskOS\u002Faskos-server\u002Finternal\u002Fsys_user\u002Finternal\u002Frepository#  tree\n.\n├── cache\n│   └── sys_user.go\n├── dao\n│   └── sys_user.go\n└── sys_user.go\n","bash",[31,319,320,328,333,341,352,359,367],{"__ignoreMap":29},[34,321,322,325],{"class":36,"data-line":37,"line":37},[34,323,324],{"class":44},"root@pzj:\u002Fcode\u002Fprogram\u002FAskOS\u002Faskos-server\u002Finternal\u002Fsys_user\u002Finternal\u002Frepository#",[34,326,327],{"class":121},"  tree\n",[34,329,330],{"class":36,"data-line":76,"line":76},[34,331,332],{"class":220},".\n",[34,334,335,338],{"class":36,"data-line":111,"line":111},[34,336,337],{"class":44},"├──",[34,339,340],{"class":121}," cache\n",[34,342,343,346,349],{"class":36,"data-line":128,"line":128},[34,344,345],{"class":44},"│",[34,347,348],{"class":121},"   └──",[34,350,351],{"class":121}," sys_user.go\n",[34,353,354,356],{"class":36,"data-line":143,"line":143},[34,355,337],{"class":44},[34,357,358],{"class":121}," dao\n",[34,360,361,363,365],{"class":36,"data-line":156,"line":156},[34,362,345],{"class":44},[34,364,348],{"class":121},[34,366,351],{"class":121},[34,368,369,372],{"class":36,"data-line":163,"line":163},[34,370,371],{"class":44},"└──",[34,373,351],{"class":121},[10,375,376],{},"然后redis一般在仓储层【repo】当中注入",[24,378,380],{"className":26,"code":379,"language":28,"meta":29,"style":29},"func NewSysUserRepository(dao dao.ISysUserDao, cache *cache.SysUserCache) *SysUserRepository {\n\treturn &SysUserRepository{dao: dao, cache: cache}\n}\n\ntype SysUserRepository struct {\n\tdao   dao.ISysUserDao\n\tcache *cache.SysUserCache\n}\n",[31,381,382,431,450,454,458,473,487,503],{"__ignoreMap":29},[34,383,384,386,389,391,395,398,400,403,405,408,411,413,415,418,420,422,424,427,429],{"class":36,"data-line":37,"line":37},[34,385,41],{"class":40},[34,387,388],{"class":44}," NewSysUserRepository",[34,390,49],{"class":48},[34,392,394],{"class":393},"s4XuR","dao",[34,396,397],{"class":44}," dao",[34,399,65],{"class":55},[34,401,402],{"class":44},"ISysUserDao",[34,404,246],{"class":55},[34,406,407],{"class":393},"cache",[34,409,410],{"class":40}," *",[34,412,407],{"class":44},[34,414,65],{"class":55},[34,416,417],{"class":44},"SysUserCache",[34,419,52],{"class":48},[34,421,56],{"class":55},[34,423,59],{"class":40},[34,425,426],{"class":44},"SysUserRepository",[34,428,56],{"class":55},[34,430,73],{"class":48},[34,432,433,435,437,440,442,445,448],{"class":36,"data-line":76,"line":76},[34,434,80],{"class":79},[34,436,295],{"class":40},[34,438,439],{"class":40}," &",[34,441,426],{"class":44},[34,443,444],{"class":95},"{",[34,446,447],{"class":55},"dao: dao, cache: cache",[34,449,287],{"class":95},[34,451,452],{"class":36,"data-line":111,"line":111},[34,453,287],{"class":48},[34,455,456],{"class":36,"data-line":128,"line":128},[34,457,160],{"emptyLinePlaceholder":159},[34,459,460,463,466,469,471],{"class":36,"data-line":143,"line":143},[34,461,462],{"class":40},"type",[34,464,465],{"class":44}," SysUserRepository",[34,467,468],{"class":40}," struct",[34,470,56],{"class":55},[34,472,73],{"class":48},[34,474,475,477,480,482,484],{"class":36,"data-line":156,"line":156},[34,476,80],{"class":79},[34,478,479],{"class":55},"dao   ",[34,481,394],{"class":44},[34,483,65],{"class":55},[34,485,486],{"class":44},"ISysUserDao\n",[34,488,489,491,494,496,498,500],{"class":36,"data-line":163,"line":163},[34,490,80],{"class":79},[34,492,493],{"class":55},"cache ",[34,495,59],{"class":40},[34,497,407],{"class":44},[34,499,65],{"class":55},[34,501,502],{"class":44},"SysUserCache\n",[34,504,505],{"class":36,"data-line":172,"line":172},[34,506,287],{"class":48},[10,508,509,510,512],{},"cache模块放在与",[31,511,394],{"code":394},"同级的目录下，用来缓存数据",[10,514,515],{},"cache模块主要编写redis相关的缓存代码:",[517,518,519,526,532],"ol",{},[520,521,522,525],"li",{},[31,523,524],{"code":524},"Key()",": 获取redis对应的key值，简化代码",[520,527,528,531],{},[31,529,530],{"code":530},"Get",": 获取缓存数据",[520,533,534,537],{},[31,535,536],{"code":536},"Set",": 写入缓存数据",[10,539,540],{},"具体如下：",[24,542,544],{"className":26,"code":543,"language":28,"meta":29,"style":29},"package cache\n\nimport (\n\t\"context\"\n\t\"encoding\u002Fjson\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com\u002Fcodepzj\u002Faskos-server\u002Finternal\u002Fsys_user\u002Finternal\u002Fdomain\"\n\t\"github.com\u002Fredis\u002Fgo-redis\u002Fv9\"\n)\n\nvar (\n\tErrUserNotFound  = redis.Nil\n\tSysUserCacheTime = 10 * time.Minute\n)\n\ntype SysUserCache struct {\n\tclient   *redis.Client\n\tduration time.Duration\n}\n\nfunc NewSysUserCache(client *redis.Client) *SysUserCache {\n\treturn &SysUserCache{\n\t\tclient:   client,\n\t\tduration: SysUserCacheTime,\n\t}\n}\n\nfunc (cache *SysUserCache) Key(id uint) string {\n\treturn fmt.Sprintf(\"user:info:%d\", id)\n}\n\n\u002F\u002F 获得redis缓存中的数据，不考虑业务逻辑\n\u002F\u002F 只看redis中是否真的有数据，没有则返回错误\nfunc (cache *SysUserCache) Get(id uint) (*domain.SysUserInfo, error) {\n\tval, err := cache.client.Get(context.Background(), cache.Key(id)).Result()\n\tvar user domain.SysUserInfo\n\t\u002F\u002F 未命中缓存\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\terr = json.Unmarshal([]byte(val), &user)\n\treturn &user, err\n}\n\n\u002F\u002F 设置缓存\nfunc (cache *SysUserCache) Set(u *domain.SysUserInfo) error {\n\tval, err := json.Marshal(u)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn cache.client.Set(context.Background(), cache.Key(u.ID), val, cache.duration).Err()\n}\n",[31,545,546,553,557,567,580,591,602,613,617,628,639,643,647,656,670,688,693,698,712,729,744,749,754,787,800,810,820,829,834,839,880,908,913,918,924,930,984,1030,1047,1055,1073,1087,1096,1139,1151,1156,1161,1167,1211,1231,1248,1260,1269,1315],{"__ignoreMap":29},[34,547,548,551],{"class":36,"data-line":37,"line":37},[34,549,550],{"class":40},"package",[34,552,340],{"class":44},[34,554,555],{"class":36,"data-line":76,"line":76},[34,556,160],{"emptyLinePlaceholder":159},[34,558,559,562,564],{"class":36,"data-line":111,"line":111},[34,560,561],{"class":40},"import",[34,563,56],{"class":55},[34,565,566],{"class":48},"(\n",[34,568,569,571,574,577],{"class":36,"data-line":128,"line":128},[34,570,80],{"class":79},[34,572,573],{"class":121},"\"",[34,575,576],{"class":44},"context",[34,578,579],{"class":121},"\"\n",[34,581,582,584,586,589],{"class":36,"data-line":143,"line":143},[34,583,80],{"class":79},[34,585,573],{"class":121},[34,587,588],{"class":44},"encoding\u002Fjson",[34,590,579],{"class":121},[34,592,593,595,597,600],{"class":36,"data-line":156,"line":156},[34,594,80],{"class":79},[34,596,573],{"class":121},[34,598,599],{"class":44},"fmt",[34,601,579],{"class":121},[34,603,604,606,608,611],{"class":36,"data-line":163,"line":163},[34,605,80],{"class":79},[34,607,573],{"class":121},[34,609,610],{"class":44},"time",[34,612,579],{"class":121},[34,614,615],{"class":36,"data-line":172,"line":172},[34,616,160],{"emptyLinePlaceholder":159},[34,618,619,621,623,626],{"class":36,"data-line":228,"line":228},[34,620,80],{"class":79},[34,622,573],{"class":121},[34,624,625],{"class":44},"github.com\u002Fcodepzj\u002Faskos-server\u002Finternal\u002Fsys_user\u002Finternal\u002Fdomain",[34,627,579],{"class":121},[34,629,630,632,634,637],{"class":36,"data-line":257,"line":257},[34,631,80],{"class":79},[34,633,573],{"class":121},[34,635,636],{"class":44},"github.com\u002Fredis\u002Fgo-redis\u002Fv9",[34,638,579],{"class":121},[34,640,641],{"class":36,"data-line":280,"line":280},[34,642,153],{"class":48},[34,644,645],{"class":36,"data-line":290,"line":290},[34,646,160],{"emptyLinePlaceholder":159},[34,648,649,652,654],{"class":36,"data-line":301,"line":301},[34,650,651],{"class":40},"var",[34,653,56],{"class":55},[34,655,566],{"class":48},[34,657,659,661,664,667],{"class":36,"data-line":658,"line":658},14,[34,660,80],{"class":79},[34,662,663],{"class":55},"ErrUserNotFound  ",[34,665,666],{"class":40},"=",[34,668,669],{"class":55}," redis.Nil\n",[34,671,673,675,678,680,683,685],{"class":36,"data-line":672,"line":672},15,[34,674,80],{"class":79},[34,676,677],{"class":55},"SysUserCacheTime ",[34,679,666],{"class":40},[34,681,682],{"class":220}," 10",[34,684,410],{"class":40},[34,686,687],{"class":55}," time.Minute\n",[34,689,691],{"class":36,"data-line":690,"line":690},16,[34,692,153],{"class":48},[34,694,696],{"class":36,"data-line":695,"line":695},17,[34,697,160],{"emptyLinePlaceholder":159},[34,699,701,703,706,708,710],{"class":36,"data-line":700,"line":700},18,[34,702,462],{"class":40},[34,704,705],{"class":44}," SysUserCache",[34,707,468],{"class":40},[34,709,56],{"class":55},[34,711,73],{"class":48},[34,713,715,717,720,722,724,726],{"class":36,"data-line":714,"line":714},19,[34,716,80],{"class":79},[34,718,719],{"class":55},"client   ",[34,721,59],{"class":40},[34,723,62],{"class":44},[34,725,65],{"class":55},[34,727,728],{"class":44},"Client\n",[34,730,732,734,737,739,741],{"class":36,"data-line":731,"line":731},20,[34,733,80],{"class":79},[34,735,736],{"class":55},"duration ",[34,738,610],{"class":44},[34,740,65],{"class":55},[34,742,743],{"class":44},"Duration\n",[34,745,747],{"class":36,"data-line":746,"line":746},21,[34,748,287],{"class":48},[34,750,752],{"class":36,"data-line":751,"line":751},22,[34,753,160],{"emptyLinePlaceholder":159},[34,755,757,759,762,764,767,769,771,773,775,777,779,781,783,785],{"class":36,"data-line":756,"line":756},23,[34,758,41],{"class":40},[34,760,761],{"class":44}," NewSysUserCache",[34,763,49],{"class":48},[34,765,766],{"class":393},"client",[34,768,410],{"class":40},[34,770,62],{"class":44},[34,772,65],{"class":55},[34,774,68],{"class":44},[34,776,52],{"class":48},[34,778,56],{"class":55},[34,780,59],{"class":40},[34,782,417],{"class":44},[34,784,56],{"class":55},[34,786,73],{"class":48},[34,788,790,792,794,796,798],{"class":36,"data-line":789,"line":789},24,[34,791,80],{"class":79},[34,793,295],{"class":40},[34,795,439],{"class":40},[34,797,417],{"class":44},[34,799,73],{"class":95},[34,801,803,805,807],{"class":36,"data-line":802,"line":802},25,[34,804,80],{"class":79},[34,806,80],{"class":79},[34,808,809],{"class":55},"client:   client,\n",[34,811,813,815,817],{"class":36,"data-line":812,"line":812},26,[34,814,80],{"class":79},[34,816,80],{"class":79},[34,818,819],{"class":55},"duration: SysUserCacheTime,\n",[34,821,823,825,827],{"class":36,"data-line":822,"line":822},27,[34,824,80],{"class":79},[34,826,29],{"class":55},[34,828,287],{"class":95},[34,830,832],{"class":36,"data-line":831,"line":831},28,[34,833,287],{"class":48},[34,835,837],{"class":36,"data-line":836,"line":836},29,[34,838,160],{"emptyLinePlaceholder":159},[34,840,842,844,846,848,850,852,854,856,858,861,863,866,869,871,873,876,878],{"class":36,"data-line":841,"line":841},30,[34,843,41],{"class":40},[34,845,56],{"class":55},[34,847,49],{"class":48},[34,849,493],{"class":393},[34,851,59],{"class":40},[34,853,417],{"class":44},[34,855,52],{"class":48},[34,857,56],{"class":55},[34,859,860],{"class":44},"Key",[34,862,49],{"class":48},[34,864,865],{"class":393},"id",[34,867,868],{"class":40}," uint",[34,870,52],{"class":48},[34,872,56],{"class":55},[34,874,875],{"class":40},"string",[34,877,56],{"class":55},[34,879,73],{"class":48},[34,881,883,885,887,890,893,895,898,901,903,906],{"class":36,"data-line":882,"line":882},31,[34,884,80],{"class":79},[34,886,295],{"class":40},[34,888,889],{"class":55}," fmt.",[34,891,892],{"class":44},"Sprintf",[34,894,49],{"class":95},[34,896,897],{"class":121},"\"user:info:",[34,899,900],{"class":220},"%d",[34,902,573],{"class":121},[34,904,905],{"class":55},", id",[34,907,153],{"class":95},[34,909,911],{"class":36,"data-line":910,"line":910},32,[34,912,287],{"class":48},[34,914,916],{"class":36,"data-line":915,"line":915},33,[34,917,160],{"emptyLinePlaceholder":159},[34,919,921],{"class":36,"data-line":920,"line":920},34,[34,922,923],{"class":168},"\u002F\u002F 获得redis缓存中的数据，不考虑业务逻辑\n",[34,925,927],{"class":36,"data-line":926,"line":926},35,[34,928,929],{"class":168},"\u002F\u002F 只看redis中是否真的有数据，没有则返回错误\n",[34,931,933,935,937,939,941,943,945,947,949,951,953,955,957,959,961,963,965,968,970,973,975,978,980,982],{"class":36,"data-line":932,"line":932},36,[34,934,41],{"class":40},[34,936,56],{"class":55},[34,938,49],{"class":48},[34,940,493],{"class":393},[34,942,59],{"class":40},[34,944,417],{"class":44},[34,946,52],{"class":48},[34,948,56],{"class":55},[34,950,530],{"class":44},[34,952,49],{"class":48},[34,954,865],{"class":393},[34,956,868],{"class":40},[34,958,52],{"class":48},[34,960,56],{"class":55},[34,962,49],{"class":48},[34,964,59],{"class":40},[34,966,967],{"class":44},"domain",[34,969,65],{"class":55},[34,971,972],{"class":44},"SysUserInfo",[34,974,246],{"class":55},[34,976,977],{"class":40},"error",[34,979,52],{"class":48},[34,981,56],{"class":55},[34,983,73],{"class":48},[34,985,987,989,992,994,997,999,1001,1003,1005,1007,1009,1012,1014,1016,1018,1020,1022,1024,1026,1028],{"class":36,"data-line":986,"line":986},37,[34,988,80],{"class":79},[34,990,991],{"class":55},"val, err ",[34,993,86],{"class":40},[34,995,996],{"class":55}," cache.client.",[34,998,530],{"class":44},[34,1000,49],{"class":95},[34,1002,193],{"class":55},[34,1004,196],{"class":44},[34,1006,49],{"class":108},[34,1008,52],{"class":108},[34,1010,1011],{"class":55},", cache.",[34,1013,860],{"class":44},[34,1015,49],{"class":108},[34,1017,865],{"class":55},[34,1019,52],{"class":108},[34,1021,52],{"class":95},[34,1023,65],{"class":55},[34,1025,207],{"class":44},[34,1027,49],{"class":95},[34,1029,153],{"class":95},[34,1031,1033,1035,1037,1040,1042,1044],{"class":36,"data-line":1032,"line":1032},38,[34,1034,80],{"class":79},[34,1036,651],{"class":40},[34,1038,1039],{"class":55}," user ",[34,1041,967],{"class":44},[34,1043,65],{"class":55},[34,1045,1046],{"class":44},"SysUserInfo\n",[34,1048,1050,1052],{"class":36,"data-line":1049,"line":1049},39,[34,1051,80],{"class":79},[34,1053,1054],{"class":168},"\u002F\u002F 未命中缓存\n",[34,1056,1058,1060,1062,1065,1067,1069,1071],{"class":36,"data-line":1057,"line":1057},40,[34,1059,80],{"class":79},[34,1061,177],{"class":40},[34,1063,1064],{"class":55}," err ",[34,1066,217],{"class":40},[34,1068,221],{"class":220},[34,1070,56],{"class":55},[34,1072,73],{"class":95},[34,1074,1076,1078,1080,1082,1084],{"class":36,"data-line":1075,"line":1075},41,[34,1077,80],{"class":79},[34,1079,80],{"class":79},[34,1081,295],{"class":40},[34,1083,221],{"class":220},[34,1085,1086],{"class":55},", err\n",[34,1088,1090,1092,1094],{"class":36,"data-line":1089,"line":1089},42,[34,1091,80],{"class":79},[34,1093,29],{"class":55},[34,1095,287],{"class":95},[34,1097,1099,1101,1104,1106,1109,1112,1114,1117,1120,1123,1125,1128,1130,1132,1134,1137],{"class":36,"data-line":1098,"line":1098},43,[34,1100,80],{"class":79},[34,1102,1103],{"class":55},"err ",[34,1105,666],{"class":40},[34,1107,1108],{"class":55}," json.",[34,1110,1111],{"class":44},"Unmarshal",[34,1113,49],{"class":95},[34,1115,1116],{"class":108},"[",[34,1118,1119],{"class":108},"]",[34,1121,1122],{"class":40},"byte",[34,1124,49],{"class":108},[34,1126,1127],{"class":55},"val",[34,1129,52],{"class":108},[34,1131,246],{"class":55},[34,1133,98],{"class":40},[34,1135,1136],{"class":55},"user",[34,1138,153],{"class":95},[34,1140,1142,1144,1146,1148],{"class":36,"data-line":1141,"line":1141},44,[34,1143,80],{"class":79},[34,1145,295],{"class":40},[34,1147,439],{"class":40},[34,1149,1150],{"class":55},"user, err\n",[34,1152,1154],{"class":36,"data-line":1153,"line":1153},45,[34,1155,287],{"class":48},[34,1157,1159],{"class":36,"data-line":1158,"line":1158},46,[34,1160,160],{"emptyLinePlaceholder":159},[34,1162,1164],{"class":36,"data-line":1163,"line":1163},47,[34,1165,1166],{"class":168},"\u002F\u002F 设置缓存\n",[34,1168,1170,1172,1174,1176,1178,1180,1182,1184,1186,1188,1190,1193,1195,1197,1199,1201,1203,1205,1207,1209],{"class":36,"data-line":1169,"line":1169},48,[34,1171,41],{"class":40},[34,1173,56],{"class":55},[34,1175,49],{"class":48},[34,1177,493],{"class":393},[34,1179,59],{"class":40},[34,1181,417],{"class":44},[34,1183,52],{"class":48},[34,1185,56],{"class":55},[34,1187,536],{"class":44},[34,1189,49],{"class":48},[34,1191,1192],{"class":393},"u",[34,1194,410],{"class":40},[34,1196,967],{"class":44},[34,1198,65],{"class":55},[34,1200,972],{"class":44},[34,1202,52],{"class":48},[34,1204,56],{"class":55},[34,1206,977],{"class":40},[34,1208,56],{"class":55},[34,1210,73],{"class":48},[34,1212,1214,1216,1218,1220,1222,1225,1227,1229],{"class":36,"data-line":1213,"line":1213},49,[34,1215,80],{"class":79},[34,1217,991],{"class":55},[34,1219,86],{"class":40},[34,1221,1108],{"class":55},[34,1223,1224],{"class":44},"Marshal",[34,1226,49],{"class":95},[34,1228,1192],{"class":55},[34,1230,153],{"class":95},[34,1232,1234,1236,1238,1240,1242,1244,1246],{"class":36,"data-line":1233,"line":1233},50,[34,1235,80],{"class":79},[34,1237,177],{"class":40},[34,1239,1064],{"class":55},[34,1241,217],{"class":40},[34,1243,221],{"class":220},[34,1245,56],{"class":55},[34,1247,73],{"class":95},[34,1249,1251,1253,1255,1257],{"class":36,"data-line":1250,"line":1250},51,[34,1252,80],{"class":79},[34,1254,80],{"class":79},[34,1256,295],{"class":40},[34,1258,1259],{"class":55}," err\n",[34,1261,1263,1265,1267],{"class":36,"data-line":1262,"line":1262},52,[34,1264,80],{"class":79},[34,1266,29],{"class":55},[34,1268,287],{"class":95},[34,1270,1272,1274,1276,1278,1280,1282,1284,1286,1288,1290,1292,1294,1296,1299,1301,1304,1306,1308,1311,1313],{"class":36,"data-line":1271,"line":1271},53,[34,1273,80],{"class":79},[34,1275,295],{"class":40},[34,1277,996],{"class":55},[34,1279,536],{"class":44},[34,1281,49],{"class":95},[34,1283,193],{"class":55},[34,1285,196],{"class":44},[34,1287,49],{"class":108},[34,1289,52],{"class":108},[34,1291,1011],{"class":55},[34,1293,860],{"class":44},[34,1295,49],{"class":108},[34,1297,1298],{"class":55},"u.ID",[34,1300,52],{"class":108},[34,1302,1303],{"class":55},", val, cache.duration",[34,1305,52],{"class":95},[34,1307,65],{"class":55},[34,1309,1310],{"class":44},"Err",[34,1312,49],{"class":95},[34,1314,153],{"class":95},[34,1316,1318],{"class":36,"data-line":1317,"line":1317},54,[34,1319,287],{"class":48},[10,1321,1322],{},[1323,1324,1325,1326,1329,1330,1333],"strong",{},"大明老师在视频里面说，公司一般在",[31,1327,1328],{"code":1328},"repo","或者",[31,1331,1332],{"code":1332},"service","层去使用redis，实际上最佳实践是在repo层去引入redis来做缓存，原因是service其实关心的是业务逻辑，不关心拿数据具体是从redis还是从数据库拿的，所以应该把redis操作放在仓储层去实现数据的持久化",[20,1335,1336],{"id":1336},"repo中使用redis",[24,1338,1340],{"className":26,"code":1339,"language":28,"meta":29,"style":29},"func (r *SysUserRepository) GetByID(id uint) (*domain.SysUserInfo, error) {\n\tuser, err := r.cache.Get(id)\n\tif err == nil {\n\t\treturn user, nil\n\t}\n\n\t\u002F\u002F 未命中缓存\n\tif errors.Is(err, cache.ErrUserNotFound) {\n\t\tu, err := r.dao.GetByID(id)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tuser := &domain.SysUserInfo{\n\t\t\tID:        u.ID,\n\t\t\tCreatedAt: u.CreatedAt.Format(\"2006-01-02 15:04:05\"),\n\t\t\tUpdatedAt: u.UpdatedAt.Format(\"2006-01-02 15:04:05\"),\n\t\t\tUsername:  u.Username,\n\t\t\tPhone:     u.Phone,\n\t\t\tAvatar:    u.Avatar,\n\t\t\tSex:       *u.Sex,\n\t\t\tEmail:     u.Email,\n\t\t\tRoleId:    u.RoleId,\n\t\t}\n\t\t\u002F\u002F 监控缓存\n\t\tif err = r.cache.Set(user); err != nil {\n\t\t\tslog.Error(\"缓存用户信息失败\", \"err\", err.Error())\n\t\t}\n\t\treturn user, nil\n\t}\n\t\u002F\u002F redis异常【宕机，击穿】\n\t\u002F* TODO: 进阶\n\t可考虑限流，使用本地memcache进行降级操作\n\t防止数据库被打穿\n\t*\u002F\n\treturn nil, err\n}\n",[31,1341,1342,1394,1414,1431,1445,1453,1457,1463,1486,1508,1526,1540,1550,1554,1575,1586,1609,1630,1641,1652,1663,1679,1690,1701,1711,1720,1752,1785,1795,1807,1815,1822,1829,1836,1843,1850,1860],{"__ignoreMap":29},[34,1343,1344,1346,1348,1350,1353,1355,1357,1359,1361,1364,1366,1368,1370,1372,1374,1376,1378,1380,1382,1384,1386,1388,1390,1392],{"class":36,"data-line":37,"line":37},[34,1345,41],{"class":40},[34,1347,56],{"class":55},[34,1349,49],{"class":48},[34,1351,1352],{"class":393},"r ",[34,1354,59],{"class":40},[34,1356,426],{"class":44},[34,1358,52],{"class":48},[34,1360,56],{"class":55},[34,1362,1363],{"class":44},"GetByID",[34,1365,49],{"class":48},[34,1367,865],{"class":393},[34,1369,868],{"class":40},[34,1371,52],{"class":48},[34,1373,56],{"class":55},[34,1375,49],{"class":48},[34,1377,59],{"class":40},[34,1379,967],{"class":44},[34,1381,65],{"class":55},[34,1383,972],{"class":44},[34,1385,246],{"class":55},[34,1387,977],{"class":40},[34,1389,52],{"class":48},[34,1391,56],{"class":55},[34,1393,73],{"class":48},[34,1395,1396,1398,1401,1403,1406,1408,1410,1412],{"class":36,"data-line":76,"line":76},[34,1397,80],{"class":79},[34,1399,1400],{"class":55},"user, err ",[34,1402,86],{"class":40},[34,1404,1405],{"class":55}," r.cache.",[34,1407,530],{"class":44},[34,1409,49],{"class":95},[34,1411,865],{"class":55},[34,1413,153],{"class":95},[34,1415,1416,1418,1420,1422,1425,1427,1429],{"class":36,"data-line":111,"line":111},[34,1417,80],{"class":79},[34,1419,177],{"class":40},[34,1421,1064],{"class":55},[34,1423,1424],{"class":40},"==",[34,1426,221],{"class":220},[34,1428,56],{"class":55},[34,1430,73],{"class":95},[34,1432,1433,1435,1437,1439,1442],{"class":36,"data-line":128,"line":128},[34,1434,80],{"class":79},[34,1436,80],{"class":79},[34,1438,295],{"class":40},[34,1440,1441],{"class":55}," user, ",[34,1443,1444],{"class":220},"nil\n",[34,1446,1447,1449,1451],{"class":36,"data-line":143,"line":143},[34,1448,80],{"class":79},[34,1450,29],{"class":55},[34,1452,287],{"class":95},[34,1454,1455],{"class":36,"data-line":156,"line":156},[34,1456,160],{"emptyLinePlaceholder":159},[34,1458,1459,1461],{"class":36,"data-line":163,"line":163},[34,1460,80],{"class":79},[34,1462,1054],{"class":168},[34,1464,1465,1467,1469,1472,1475,1477,1480,1482,1484],{"class":36,"data-line":172,"line":172},[34,1466,80],{"class":79},[34,1468,177],{"class":40},[34,1470,1471],{"class":55}," errors.",[34,1473,1474],{"class":44},"Is",[34,1476,49],{"class":95},[34,1478,1479],{"class":55},"err, cache.ErrUserNotFound",[34,1481,52],{"class":95},[34,1483,56],{"class":55},[34,1485,73],{"class":95},[34,1487,1488,1490,1492,1495,1497,1500,1502,1504,1506],{"class":36,"data-line":228,"line":228},[34,1489,80],{"class":79},[34,1491,80],{"class":79},[34,1493,1494],{"class":55},"u, err ",[34,1496,86],{"class":40},[34,1498,1499],{"class":55}," r.dao.",[34,1501,1363],{"class":44},[34,1503,49],{"class":108},[34,1505,865],{"class":55},[34,1507,153],{"class":108},[34,1509,1510,1512,1514,1516,1518,1520,1522,1524],{"class":36,"data-line":257,"line":257},[34,1511,80],{"class":79},[34,1513,80],{"class":79},[34,1515,177],{"class":40},[34,1517,1064],{"class":55},[34,1519,217],{"class":40},[34,1521,221],{"class":220},[34,1523,56],{"class":55},[34,1525,73],{"class":108},[34,1527,1528,1530,1532,1534,1536,1538],{"class":36,"data-line":280,"line":280},[34,1529,80],{"class":79},[34,1531,80],{"class":79},[34,1533,80],{"class":79},[34,1535,295],{"class":40},[34,1537,221],{"class":220},[34,1539,1086],{"class":55},[34,1541,1542,1544,1546,1548],{"class":36,"data-line":290,"line":290},[34,1543,80],{"class":79},[34,1545,80],{"class":79},[34,1547,29],{"class":55},[34,1549,287],{"class":108},[34,1551,1552],{"class":36,"data-line":301,"line":301},[34,1553,160],{"emptyLinePlaceholder":159},[34,1555,1556,1558,1560,1563,1565,1567,1569,1571,1573],{"class":36,"data-line":658,"line":658},[34,1557,80],{"class":79},[34,1559,80],{"class":79},[34,1561,1562],{"class":55},"user ",[34,1564,86],{"class":40},[34,1566,439],{"class":40},[34,1568,967],{"class":44},[34,1570,65],{"class":55},[34,1572,972],{"class":44},[34,1574,73],{"class":108},[34,1576,1577,1579,1581,1583],{"class":36,"data-line":672,"line":672},[34,1578,80],{"class":79},[34,1580,80],{"class":79},[34,1582,80],{"class":79},[34,1584,1585],{"class":55},"ID:        u.ID,\n",[34,1587,1588,1590,1592,1594,1597,1600,1602,1605,1607],{"class":36,"data-line":690,"line":690},[34,1589,80],{"class":79},[34,1591,80],{"class":79},[34,1593,80],{"class":79},[34,1595,1596],{"class":55},"CreatedAt: u.CreatedAt.",[34,1598,1599],{"class":44},"Format",[34,1601,49],{"class":48},[34,1603,1604],{"class":121},"\"2006-01-02 15:04:05\"",[34,1606,52],{"class":48},[34,1608,125],{"class":55},[34,1610,1611,1613,1615,1617,1620,1622,1624,1626,1628],{"class":36,"data-line":695,"line":695},[34,1612,80],{"class":79},[34,1614,80],{"class":79},[34,1616,80],{"class":79},[34,1618,1619],{"class":55},"UpdatedAt: u.UpdatedAt.",[34,1621,1599],{"class":44},[34,1623,49],{"class":48},[34,1625,1604],{"class":121},[34,1627,52],{"class":48},[34,1629,125],{"class":55},[34,1631,1632,1634,1636,1638],{"class":36,"data-line":700,"line":700},[34,1633,80],{"class":79},[34,1635,80],{"class":79},[34,1637,80],{"class":79},[34,1639,1640],{"class":55},"Username:  u.Username,\n",[34,1642,1643,1645,1647,1649],{"class":36,"data-line":714,"line":714},[34,1644,80],{"class":79},[34,1646,80],{"class":79},[34,1648,80],{"class":79},[34,1650,1651],{"class":55},"Phone:     u.Phone,\n",[34,1653,1654,1656,1658,1660],{"class":36,"data-line":731,"line":731},[34,1655,80],{"class":79},[34,1657,80],{"class":79},[34,1659,80],{"class":79},[34,1661,1662],{"class":55},"Avatar:    u.Avatar,\n",[34,1664,1665,1667,1669,1671,1674,1676],{"class":36,"data-line":746,"line":746},[34,1666,80],{"class":79},[34,1668,80],{"class":79},[34,1670,80],{"class":79},[34,1672,1673],{"class":55},"Sex:       ",[34,1675,59],{"class":40},[34,1677,1678],{"class":55},"u.Sex,\n",[34,1680,1681,1683,1685,1687],{"class":36,"data-line":751,"line":751},[34,1682,80],{"class":79},[34,1684,80],{"class":79},[34,1686,80],{"class":79},[34,1688,1689],{"class":55},"Email:     u.Email,\n",[34,1691,1692,1694,1696,1698],{"class":36,"data-line":756,"line":756},[34,1693,80],{"class":79},[34,1695,80],{"class":79},[34,1697,80],{"class":79},[34,1699,1700],{"class":55},"RoleId:    u.RoleId,\n",[34,1702,1703,1705,1707,1709],{"class":36,"data-line":789,"line":789},[34,1704,80],{"class":79},[34,1706,80],{"class":79},[34,1708,29],{"class":55},[34,1710,287],{"class":108},[34,1712,1713,1715,1717],{"class":36,"data-line":802,"line":802},[34,1714,80],{"class":79},[34,1716,80],{"class":79},[34,1718,1719],{"class":168},"\u002F\u002F 监控缓存\n",[34,1721,1722,1724,1726,1728,1730,1732,1734,1736,1738,1740,1742,1744,1746,1748,1750],{"class":36,"data-line":812,"line":812},[34,1723,80],{"class":79},[34,1725,80],{"class":79},[34,1727,177],{"class":40},[34,1729,1064],{"class":55},[34,1731,666],{"class":40},[34,1733,1405],{"class":55},[34,1735,536],{"class":44},[34,1737,49],{"class":108},[34,1739,1136],{"class":55},[34,1741,52],{"class":108},[34,1743,214],{"class":55},[34,1745,217],{"class":40},[34,1747,221],{"class":220},[34,1749,56],{"class":55},[34,1751,73],{"class":108},[34,1753,1754,1756,1758,1760,1762,1764,1766,1769,1771,1774,1777,1779,1781,1783],{"class":36,"data-line":822,"line":822},[34,1755,80],{"class":79},[34,1757,80],{"class":79},[34,1759,80],{"class":79},[34,1761,235],{"class":55},[34,1763,238],{"class":44},[34,1765,49],{"class":48},[34,1767,1768],{"class":121},"\"缓存用户信息失败\"",[34,1770,246],{"class":55},[34,1772,1773],{"class":121},"\"err\"",[34,1775,1776],{"class":55},", err.",[34,1778,238],{"class":44},[34,1780,49],{"class":95},[34,1782,52],{"class":95},[34,1784,153],{"class":48},[34,1786,1787,1789,1791,1793],{"class":36,"data-line":831,"line":831},[34,1788,80],{"class":79},[34,1790,80],{"class":79},[34,1792,29],{"class":55},[34,1794,287],{"class":108},[34,1796,1797,1799,1801,1803,1805],{"class":36,"data-line":836,"line":836},[34,1798,80],{"class":79},[34,1800,80],{"class":79},[34,1802,295],{"class":40},[34,1804,1441],{"class":55},[34,1806,1444],{"class":220},[34,1808,1809,1811,1813],{"class":36,"data-line":841,"line":841},[34,1810,80],{"class":79},[34,1812,29],{"class":55},[34,1814,287],{"class":95},[34,1816,1817,1819],{"class":36,"data-line":882,"line":882},[34,1818,80],{"class":79},[34,1820,1821],{"class":168},"\u002F\u002F redis异常【宕机，击穿】\n",[34,1823,1824,1826],{"class":36,"data-line":910,"line":910},[34,1825,80],{"class":79},[34,1827,1828],{"class":168},"\u002F* TODO: 进阶\n",[34,1830,1831,1833],{"class":36,"data-line":915,"line":915},[34,1832,80],{"class":79},[34,1834,1835],{"class":168},"可考虑限流，使用本地memcache进行降级操作\n",[34,1837,1838,1840],{"class":36,"data-line":920,"line":920},[34,1839,80],{"class":79},[34,1841,1842],{"class":168},"防止数据库被打穿\n",[34,1844,1845,1847],{"class":36,"data-line":926,"line":926},[34,1846,80],{"class":79},[34,1848,1849],{"class":168},"*\u002F\n",[34,1851,1852,1854,1856,1858],{"class":36,"data-line":932,"line":932},[34,1853,80],{"class":79},[34,1855,295],{"class":40},[34,1857,221],{"class":220},[34,1859,1086],{"class":55},[34,1861,1862],{"class":36,"data-line":986,"line":986},[34,1863,287],{"class":48},[10,1865,1866],{},"来看这段代码，如果命中缓存则直接返回，不命中缓存，则回表查询，写入redis；",[10,1868,1869,1872],{},[1323,1870,1871],{},"异常兜底："," 如果redis发生异常，如宕机，雪崩等情况，可以考虑限流，并使用memcache去进行本地缓存，这叫做降级操作",[20,1874,1875],{"id":1875},"收获",[10,1877,1878],{},"虽然萌新初入门redis，但是看了大明老师的视频还是非常有收获的，懂得如何在go项目中优雅的去使用redis，操作redis。",[1880,1881,1882],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sSDpw, html code.shiki .sSDpw{--shiki-default:#005cc5;--shiki-dark:#79b8ff}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJX2D, html code.shiki .sJX2D{--shiki-default:#e36209;--shiki-dark:#ffab70}html pre.shiki code .sqkie, html code.shiki .sqkie{--shiki-default:#5a32a3;--shiki-dark:#b392f0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":29,"searchDepth":128,"depth":128,"links":1884},[1885,1886,1887,1888],{"id":22,"depth":76,"text":22},{"id":309,"depth":76,"text":309},{"id":1336,"depth":76,"text":1336},{"id":1875,"depth":76,"text":1875},[1890],"数据库","2025-08-31","这篇文章记录了我在学习极客时间大明老师课程后，对 Redis 在 Go 项目中的实践总结。从初始化 Redis 客户端，到在仓储层引入缓存模块，再到结合 DDD 思想实现数据查询与缓存的解耦，逐步形成了更优雅的使用方式。",false,"md",null,{"slots":1897},{},"\u002F2025\u002F08\u002Fredis-in-golang-practice",{"text":1900,"minutes":1901,"time":1902,"words":1903},"5 min read",4.045,242700,809,{"title":5,"description":1892},{"loc":1898},"posts\u002F2025\u002F08\u002Fredis-in-golang-practice",[62,1908],"ddd","tech","tKXi1_kPmV7iSx7ePNlkJbeUbG2wH7fL6mSmc1zl6L8",[1912,1917],{"title":1913,"path":1914,"stem":1915,"date":1916,"type":1909,"children":-1},"MySQL 事务的概念与特性","\u002F2025\u002F08\u002Fmysql-what-is-transaction","posts\u002F2025\u002F08\u002Fmysql-what-is-transaction","2025-08-28",{"title":1918,"path":1919,"stem":1920,"date":1921,"type":1909,"children":-1},"MySQL 索引原理：B+ 树","\u002F2025\u002F09\u002Fmysql-bplustree","posts\u002F2025\u002F09\u002Fmysql-bplustree","2025-09-01",1786555055914]