Singleton Design Pattern in Go

1. Definition

The Singleton Design Pattern ensures that a class has only one instance and provides a global point of access to that instance.

2. Problem Statement

In many cases, ensuring that there's a single instance of a class can save resources, especially if creating the class is resource-intensive or needs to maintain a state that should be consistent across its users.

3. Solution

To ensure a single instance, the constructor is made private and a static method is provided to get the instance. In Go, where there are no classes in the traditional sense, you can use a combination of package-level variables and the sync.Once type to achieve the same result.

4. Real-World Use Cases

1. Database connection pools: Ensuring only one pool is created can save connections and ensure consistency.

2. Logger: A global logger that writes to a file or external service.

3. Configuration: A globally accessible configuration object that's initialized once.

5. Implementation Steps

1. Declare a private package-level variable to hold the instance.

2. Declare a private package-level variable of type sync.Once.

3. Provide a function to get the instance that uses sync.Once to ensure the instance is created only once.

6. Implementation in Go

// Import necessary packages
package main
import (
    "fmt"
    "sync"
)
// Singleton type
type Singleton struct {
    data int
}
// Package-level instance and sync.Once variables
var singleInstance *Singleton
var once sync.Once
// Function to get the instance
func GetInstance() *Singleton {
    once.Do(func() {
        singleInstance = &Singleton{}
    })
    return singleInstance
}
func (s *Singleton) AddOne() int {
    s.data++
    return s.data
}
// Main function to demonstrate the singleton
func main() {
    instance := GetInstance()
    instance2 := GetInstance()
    if instance == instance2 {
        fmt.Println("Both instances are the same!")
    }
    fmt.Println(instance.AddOne())
    fmt.Println(instance2.AddOne())
}

Output:

Both instances are the same!
1
2

Explanation:

1. The Singleton struct is defined to demonstrate the pattern.

2. singleInstance is the package-level variable that will hold our single instance of Singleton.

3. The once variable is of type sync.Once which ensures that the initialization will only happen once.

4. The GetInstance function checks if the singleInstance is initialized, and if not, it initializes it. This is done in a thread-safe manner using sync.Once.

5. In the main function, two instances are fetched using GetInstance, and both are the same as demonstrated.

7. When to use?

Use the Singleton pattern when:

1. You want to eliminate the option of instantiating multiple objects.

2. A single instance can be extended by subclassing, and clients can use the extended instance without modifying the code.

3. You want to provide controlled access to the sole instance.

Note: Singleton can lead to problems if not used carefully. It can introduce a global state into an application and can be challenging to work within a concurrent environment or when unit testing.


Comments