Design Patterns in Golang - SINGLETON PATTERN

I am a full-Stack (backend leaning) software developer. Experienced with all stages of the development cycle for dynamic web projects. Well-versed in programming languages including HTML5, CSS, JAVASCRIPT, NODEJS, GOLANG, REACTJS, PYTHON, ANGULAR and IONIC.
What is the Singleton Pattern?
It's a design pattern that makes sure a class has only one instance and provides a global way to access it. This is useful when you need one instance of a class to manage actions across the system. The Singleton Pattern limits the creation of a class to just one object, ensuring there is only one instance and a global access point.
Scenario
Imagine you are the leader of a secret club, and you have a special book with all the secret plans and information for the club. This book is very important, and you want to make sure there is only one copy. If there were multiple copies, different members might write different things in each one, and it would be very confusing. In programming, sometimes we have a special object (like your secret book) that we want to make sure there is only one instance of in the whole program. This is where the Singleton Pattern comes in. The Singleton Pattern ensures that a class has only one instance and provides a global way to access it.
Why Use the Singleton Pattern?
Controlled Access to a Single Instance: Ensures that a class has only one instance and provides a single point of access to it.
Reduced Memory Footprint: Since only one instance of the class is created, it saves memory.
Consistency and Synchronization: Ensures that all objects interact with a single instance, maintaining consistency across the application.
Lazy Initialization: The instance is created only when it is needed, which can improve performance if the initialization of the instance is resource-intensive.
Implementing the Singleton Pattern in Golang
Here's an example of how to implement the Singleton Pattern in Golang:
package main
import (
"fmt"
"sync"
)
// ConfigManager holds configuration settings for the application
type ConfigManager struct {
DatabaseURL string
APIKey string
FilePath string
}
var (
configInstance *ConfigManager
once sync.Once
)
// GetConfigManagerInstance returns the singleton instance of ConfigManager
func GetConfigManagerInstance() *ConfigManager {
once.Do(func() {
configInstance = &ConfigManager{
DatabaseURL: "localhost:5432/mydb",
APIKey: "mysecretapikey",
FilePath: "/etc/app/config.json",
}
})
return configInstance
}
func main() {
// Access configuration settings through the singleton instance
config1 := GetConfigManagerInstance()
fmt.Println("Config 1:", config1.DatabaseURL, config1.APIKey, config1.FilePath)
// Access the configuration again, should be the same instance
config2 := GetConfigManagerInstance()
fmt.Println("Config 2:", config2.DatabaseURL, config2.APIKey, config2.FilePath)
// Modify the configuration through config1
config1.DatabaseURL = "localhost:5432/updateddb"
// Verify that config2 reflects the changes made through config1
fmt.Println("Config 2 after update:", config2.DatabaseURL)
}
Explanation
ConfigManager Structure: This structure holds configuration settings such as
DatabaseURL,APIKey, andFilePath.Singleton Variables: We use
configInstanceto hold the single instance ofConfigManager, andoncefrom thesyncpackage to ensure that the instance is created only once.GetConfigManagerInstance Function: This function initializes
configInstancewith the configuration settings only once, ensuring that the same instance is returned every time the function is called.Using the Singleton: In the
mainfunction, we access theConfigManagerinstance usingGetConfigManagerInstance. Bothconfig1andconfig2refer to the same instance. Any changes made through one reference are reflected when accessed through another reference.




