In Golang, you can implement a distributed lock for coordinated access to a shared resource by using the sync package and a distributed system like Redis or etcd to manage the lock. Here's a step-by-step guide:
Install the necessary dependencies:
go get github.com/go-redis/redis/v8 // Redis client library for Golang
Import the required packages:
import (
"context"
"log"
"sync"
"time"
"github.com/go-redis/redis/v8"
)
Create a global Redis client:
var redisClient *redis.Client
func init() {
redisClient = redis.NewClient(&redis.Options{
Addr: "localhost:6379", // Replace with your Redis server address
Password: "", // If your Redis server has a password
DB: 0, // Replace with the appropriate database index
})
}
Define a function to acquire the lock using Redis' SET command with options NX
(to set the key only if it doesn't exist) and a timeout to automatically release the lock in case the lock holder crashes:
func acquireLock(lockName string, timeout time.Duration) bool {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
success, err := redisClient.SetNX(ctx, lockName, "locked", timeout).Result()
if err != nil {
log.Println("Failed to acquire lock:", err)
return false
}
return success
}
Define a function to release the lock by deleting the Redis key:
func releaseLock(lockName string) {
ctx := context.Background()
_, err := redisClient.Del(ctx, lockName).Result()
if err != nil {
log.Println("Failed to release lock:", err)
}
}
Use the lock in your code:
func main() {
lockName := "my_lock"
// Acquire the lock
if acquireLock(lockName, time.Second*10) {
defer releaseLock(lockName)
// Perform operations with the shared resource here
} else {
log.Println("Failed to acquire lock")
}
// Continue executing the rest of your code
}
Make sure that your Redis server is running and accessible at the specified address.