Singleton Pattern
The Singleton Pattern is a creational design pattern that ensures a class has only one instance and provides a global point of access to that instance. This pattern is particularly useful when there's a need to coordinate actions that can't be shared among multiple instances.
Implementing the Singleton Pattern in Go
Let's dive into a practical example of implementing the Singleton Pattern in Go. We'll create a DriverPg
type that represents a PostgreSQL database driver connection. The Connect
function initializes and returns the singleton instance in a thread-safe manner using sync.Once
.
package main
import (
"fmt"
"sync"
"time"
)
var (
once sync.Once
instance *DriverPg
)
// DriverPg represents a PostgreSQL database driver connection.
type DriverPg struct {
conn string
}
// Connect returns the singleton instance of DriverPg.
func Connect() *DriverPg {
once.Do(func() {
instance = &DriverPg{conn: "DriverConnectPostgres"}
})
return instance
}
func main() {
// Simulate a delayed call to Connect.
go func() {
time.Sleep(time.Millisecond * 600)
fmt.Println(*Connect())
}()
// Create 100 goroutines.
for i := 0; i < 100; i++ {
go func(ix int) {
time.Sleep(time.Millisecond * 60)
fmt.Println(ix, " = ", Connect().conn)
}(i)
}
fmt.Scanln()
}
In this example, the DriverPg
type represents a database driver connection. The Connect
function ensures that the initialization code is executed only once using the once.Do
construct from the sync
package. This guarantees the thread-safe creation of a single instance of DriverPg
.
The code demonstrates that despite multiple concurrent calls to Connect
, the initialization logic is executed only once, ensuring that all goroutines share the same instance of DriverPg
.
Conclusion π₯
The Singleton Pattern with sync.Once is a robust and elegant solution for managing single instances across multiple goroutines. By combining the benefits of the traditional Singleton Pattern with thread-safety, this approach enables secure and efficient access to shared resources and configurations.
Top comments (1)
Nice. Another option is to use init()