Introduction
In this project, you will learn how to implement a caching library that supports expiration time based on the singleflight package in Go. This caching library can be used in distributed systems to cache the execution results of requests, improving the performance of your application.
👀 Preview
$ /usr/local/go/bin/go test --race
PASS
ok cacheflight 1.263s
🎯 Tasks
In this project, you will learn:
- How to initialize a Go module and install the required packages
- How to implement the caching library using the
singleflightpackage - How to test the caching library to ensure it works as expected
🏆 Achievements
After completing this project, you will be able to:
- Understand the basic concepts of caching and the
singleflightpackage in Go - Implement a caching library that supports expiration time
- Integrate the caching library into your distributed system to improve the performance of your application
Initialize the Module and Install Required Packages
In this step, you will learn how to initialize the module and install the required packages for the project.
Open the terminal in the
/home/labex/projectdirectory.Initialize the module using the following command:
/usr/local/go/bin/go mod init cacheflightInstall the required packages using the following commands:
/usr/local/go/bin/go get github.com/golang/groupcache/singleflight /usr/local/go/bin/go get github.com/stretchr/testify/assert
Implement the Caching Library
In this step, you will implement the caching library based on the singleflight package.
Open the
cacheflight.gofile in the/home/labex/projectdirectory.Add the necessary content to
import.import ( "sync" "time" "github.com/golang/groupcache/singleflight" )Add the necessary content to
type Groupandtype cacheResult.// cacheResult is cache result type cacheResult struct { data interface{} // the cache data ctime time.Time // cache create time isRunning chan bool // is the function running } // Group is core struct type Group struct { cacheExpiration time.Duration // cache expiration sfg *singleflight.Group // singleflight group cache map[string]cacheResult // cache result mu sync.Mutex // mutex }Implement the
NewGroupfunction to return a new caching group with the specified cache expiration time.func NewGroup(cacheExpiration time.Duration) (group *Group) { group = &Group{ sfg: &singleflight.Group{}, cache: make(map[string]cacheResult), cacheExpiration: cacheExpiration, } return }Implement the
dofunction to handle the caching logic.func (g *Group) do(key string, fn func() (interface{}, error)) (ret interface{}, err error) { return g.sfg.Do(key, func() (interface{}, error) { g.mu.Lock() result, ok := g.cache[key] if result.isRunning != nil { g.mu.Unlock() // wait for fn done <-result.isRunning return g.do(key, fn) } else if !ok || result.ctime.Add(g.cacheExpiration).Before(time.Now()) { // if the cache is not exist or expired var run = make(chan bool) result.isRunning = run g.cache[key] = result // when fn done and close run channel, let other goroutine can get the cache defer close(run) } else { // if the cache is exist and not expired g.mu.Unlock() return result.data, nil } g.mu.Unlock() // different key can run at the same time ret, err = fn() if err != nil { return ret, nil } result = cacheResult{ data: ret, ctime: time.Now(), } g.mu.Lock() g.cache[key] = result g.mu.Unlock() return ret, nil }) }Implement the
Dofunction to be a wrapper around thedofunction.func (g *Group) Do(key string, fn func() (interface{}, error)) (ret interface{}, err error) { return g.do(key, fn) }
Test the Caching Library
In this step, you will test the caching library to ensure it works as expected.
Open the terminal in the
/home/labex/projectdirectory.Run the following command to execute the tests:
cd /home/labex/project /usr/local/go/bin/go test --raceIf the cache function has been implemented correctly, you will see the following output:
PASS ok cacheflight 1.263sIf you encounter a timeout error, execute the following commands in the terminal and then click the re-inspect button to pass the check:
cd /home/labex/project /usr/local/go/bin/go test --race
Congratulations! You have successfully implemented the caching library based on the singleflight package. You can now use this library in your distributed system to cache the execution results of requests and improve the performance of your application.
Summary
Congratulations! You have completed this project. You can practice more labs in LabEx to improve your skills.



