Home  >  Article  >  Backend Development  >  An in-depth analysis of the singleton pattern in Go language

An in-depth analysis of the singleton pattern in Go language

青灯夜游
青灯夜游Original
2023-03-21 18:36:452603browse

The singleton pattern is a common design pattern that allows only one instance to be created in the system to control access to certain resources. In the Go language, there are many ways to implement the singleton pattern. This article will give you an in-depth understanding of the implementation of the singleton pattern in the Go language.

An in-depth analysis of the singleton pattern in Go language

What is the singleton pattern

The singleton pattern refers to a design pattern that only allows the creation of one object. It is usually used to control access to certain resources, such as database connections, thread pools, etc. Through the singleton mode, you can ensure that only one instance exists in the system and provide a global access point for other objects to use.

How to implement singleton mode in Go

The Go language provides a variety of ways to implement singleton mode, including the following methods:

Method 1: Lazy style

Lazy style is a common way to implement the singleton pattern, which is characterized by creating a singleton instance when it is first used. The implementation method is as follows:

package singleton

import "sync"

var (
	instance *Singleton
	once     sync.Once
)

type Singleton struct {
}

func GetInstance() *Singleton {
	once.Do(func() {
		instance = &Singleton{}
	})

	return instance
}

In the above code, we define a structure named Singleton and instantiate it as instance. At the same time, use the sync.Once object once in the sync package to implement logic that is executed only once during the program life cycle. When GetInstance is called for the first time, the Do method of Sync.Once will call the passed in function. The logic of this function is to instantiate the Singleton object and assign it to instance. In subsequent calls to GetInstance, since instance has already been instantiated, it will not be created again.

Method 2: Hungry Chinese style

Hungry Chinese style is another common way to implement the singleton pattern, which is characterized by creating a singleton when the system starts. Instance, the instance is returned directly when called. The implementation method is as follows:

package singleton

var instance *Singleton = &Singleton{}

type Singleton struct {
}

func GetInstance() *Singleton {
	return instance
}

In the above code, we created a Singleton object during package initialization and assigned it as instance. The GetInstace method directly returns the instance, so each call returns the same object, achieving the purpose of controlling the object instance.

Method 3: Double-check locking

Double-check locking is a singleton mode implementation used in a multi-threaded environment. Its characteristic is to first check whether it has been There is an instance, if not, enter the synchronization code block to create it. The implementation method is as follows:

package singleton

import "sync"

var (
	instance *Singleton
	mu       sync.Mutex
)

type Singleton struct {
}

func GetInstance() *Singleton {
	if instance == nil {
		mu.Lock()
		defer mu.Unlock()
		if instance == nil {
			instance = &Singleton{}
		}
	}
	return instance
}

In the above code, we use a mutex lock to implement concurrency control to ensure that only one thread can access critical resources in a multi-threaded environment. At the same time, a double check mechanism is used to reduce the frequency of mutex lock use.

Example

Through the following example, we can understand how to use the singleton pattern to implement data caching.

package main

import (
	"fmt"
	"sync"
)

type Cache struct {
	store map[string]string
	mu    sync.Mutex
}

var instance *Cache

func GetCacheInstance() *Cache {
	if instance == nil {
		instance = &Cache{
			store: make(map[string]string),
		}
	}
	return instance
}

func (c *Cache) Get(key string) (string, bool) {
	c.mu.Lock()
	defer c.mu.Unlock()

	val, ok := c.store[key]
	return val, ok
}

func (c *Cache) Set(key, val string) {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.store[key] = val
}

func main() {
	cache := GetCacheInstance()

	cache.Set("name", "Tom")
	if val, ok := cache.Get("name"); ok {
		fmt.Println(val)
	}
}

In the above code, we define a Cache structure to represent data caching. Cache contains Store member variables for storing key-value pairs, and uses mutex mu to control access. The GetCacheInstance function returns a Cache instance, which represents the data cache. When called for the first time, the instance will be instantiated into a Cache object. The main function in the example demonstrates how to use a singleton Cache object to store and retrieve data.

Summary

The singleton pattern is a common design pattern that ensures that only one instance exists in the system and provides a global access point. In the Go language, there are many ways to implement the singleton pattern, including lazy style, hungry style, double-check locking, etc. Through this article, we understand the specific details of these implementation methods and implement an example of data caching.

Recommended learning: Golang tutorial

The above is the detailed content of An in-depth analysis of the singleton pattern in Go language. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn