Singleton Design Pattern
The Singleton pattern is a creational design pattern that ensures a class has only one instance and provides a global access point to it.
In software development, there are situations where we need to restrict the instantiation of a class to a single object. This is particularly useful when dealing with shared resources or managing global state.
The Singleton pattern is implemented by defining a class with a private constructor and a static method. The first time the static method is called, it creates a new instance of the class. In subsequent calls, it returns the existing instance.
The Singleton pattern provides the following benefits:
- Ensures that there is only one instance of a class in the application.
- Provides a global access point to that instance.
- Delays the initialization of the instance, improving performance and resource utilization.
The following are two implementations of the Singleton pattern in Go, each demonstrating how to connect to a database:
Hungry Singleton
In Go language, the Hungry Singleton pattern is a design pattern that creates and initializes an object at program startup. Here is how to rewrite the getDB() function using the Hungry Singleton pattern:
package main
import (
"fmt"
"sync"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Member struct {
ID string `gorm:"primaryKey;size:16"`
Name string `gorm:"size:255"`
Age int64 `gorm:"size:10"`
}
var db *gorm.DB
func init() {
fmt.Println("init")
db = func() *gorm.DB {
dsn := "user:pw@tcp(127.0.0.1:3306)/database?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("Failed to connect to database: " + err.Error())
}
fmt.Println("Connection to database!")
return db
}()
}
var o sync.Once
func getDB() *gorm.DB {
return db
}
func main() {
fmt.Println("main")
Db := getDB()
fmt.Println("addr", &Db, Db)
var members = Member{ID: "1"}
Db.Find(&members)
fmt.Println(members)
Db2 := getDB()
fmt.Println("addr", &Db2, Db2)
var members2 = Member{ID: "2"}
Db2.Find(&members2)
fmt.Println(members2)
}
Lazy Singleton
In Go language, the Lazy Singleton pattern is a design pattern that creates and initializes an object only when it is first needed. Here is how to rewrite the getDB() function using the Lazy Singleton pattern:
package main
import (
"fmt"
"sync"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Member struct {
ID string `gorm:"primaryKey;size:16"`
Name string `gorm:"size:255"`
Age int64 `gorm:"size:10"`
}
var (
db *gorm.DB
o sync.Once
)
func getDB() *gorm.DB {
o.Do(func() {
db = func() *gorm.DB {
dsn := "user:password@tcp(127.0.0.1:3306)/database?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("Failed to connect to database: " + err.Error())
}
fmt.Println("Connection to database!")
return db
}()
})
return db
}
func main() {
fmt.Println("main")
Db := getDB()
fmt.Println("addr", &Db, Db)
var members = Member{ID: "1"}
Db.Find(&members)
fmt.Println(members)
Db2 := getDB()
fmt.Println("addr", &Db2, Db2)
var members2 = Member{ID: "2"}
Db2.Find(&members2)
fmt.Println(members2)
}