Go unlocks the singleton pattern of design pattern

Time:2020-9-28

preface

Hello, everyone. I’m asong. This is my 16th original article. Thank you for your attention. Today, I’d like to share with you the singleton pattern of design pattern and implement it with go language. The students who are familiar with Java must be familiar with singleton pattern, which is a very common software design pattern. In its core structure, there is only a special class called singleton. The singleton pattern can ensure that there is only one instance of a class in the system, and the instance is easy to be accessed by the outside world, so it is convenient to control the number of instances and save system resources. Let’s take a look at how to use go to implement singleton mode. There is a small hole here. We must pay attention to it. At the end, we will tell you

What is singleton mode

The singleton pattern ensures that there is only one instance of a class. Why ensure that there is only one instance of a class? When do you need singleton mode? It seems useless to have only one instance of a class! Let’s take an example. For example, there is a class in our app that is used to save some state information of the runtime. If the class implementation is not a singleton, then the components in the app can generate multiple classes at will to save their own state, which is equal to everyone playing their own. Then the global status information will become a joke. If the class is implemented as a singleton, no matter which component of the app gets the same object (for example, application class, except in the case of multiple processes).

Go unlocks the singleton pattern of design pattern

The model of the hungry man

Here we use three ways to realize the model of starving men. First of all, let’s talk about the lazy man mode. From the word “lazy man”, we can know that this person is very lazy, so he can’t create an object without using an instance. He will definitely create an instance when he is using it. The advantage of this is that the instance can be created only when it is used. Let’s take a look at his implementation

  • No lock
package one

type singleton struct {

}

var  instance *singleton
func GetInstance() *singleton {
    if instance == nil{
        instance = new(singleton)
    }
    return instance
}

This method will have thread safety problems. In case of high concurrency, multiple threads will drop this method at the same time, and all of them will be detectedinstanceNil, which will lead to the creation of multiple objects, so this method is not recommended. Let me look at the second method.

  • The whole method is locked
type singleton struct {

}

var instance *singleton
var lock sync.Mutex

func GetInstance() *singleton {
    lock.Lock()
    defer lock.Unlock()
    if instance == nil{
        instance = new(singleton)
    }
    return instance
}

The whole method is locked here, which can solve the problem of concurrent security, but the efficiency will be reduced. Each object is locked and unlocked when creating, which slows down the speed. Therefore, this method is not recommended.

  • Lock when creating methods
type singleton struct {

}

var instance *singleton
var lock sync.Mutex

func GetInstance() *singleton {
    if instance == nil{
        lock.Lock()
        instance = new(singleton)
        lock.Unlock()
    }
    return instance
}

This method is also thread unsafe. Although we have locks, multiple threads will also cause multiple instances to be created, so this method is not recommended. So there is the following double search mechanism

  • Double check lock
type singleton struct {
    
}

var instance *singleton
var lock sync.Mutex

func GetInstance() *singleton {
    if instance == nil{
        lock.Lock()
        if instance == nil{
            instance = new(singleton)
        }
        lock.Unlock()
    }
    return instance
}

Here, the above code has been improved. Only when the object is not initialized, there will be lock and unlock operations. But there is another problem: every visit must be checked twice. In order to solve this problem, we can use the methods in the golang standard package for atomic operations.

  • Atomic operation implementation
type singleton struct {
    
}

var instance *singleton
var once sync.Once
func GetInstance() *singleton {
    once.Do(func() {
        instance = new(singleton)
    })
    return instance
}

It’s used heresync.OnceOfDoMethod can only run the callback once in the process of program running, so that only one object can be created. This method is recommended ~~~.

The model of the hungry man

There are lazy man mode, of course, there are also hungry man mode. After looking at the lazy man mode, we can explain it very well. Because he is hungry, he is very anxious to create an instance without waiting to use it. In this way, every time we call the interface, we will not create a new object, but directly return the object created before. Applicable to: if a singleton is used less times and there are more resources to create singleton messages, you need to create singletons on demand. At this time, lazy man mode is a good choice. However, there are also disadvantages. The hungry man mode will create a singleton object when the package is loaded. When the object is not used in the program, a part of the space is wasted. However, compared with the lazy mode, there is no need for locking operation, which will be safer, but will slow down the startup speed.

Let’s take a look at the go implementation of the hungry man mode

type singleton struct {

}

var instance = new(singleton)

func GetInstance()  *singleton{
    return instance
}

perhaps
type singleton struct {

}

var instance *singleton

func init()  {
    instance = new(singleton)
}

func GetInstance()  *singleton{
    return instance
}

Both methods can be used. The first method is to create a global variable, and the second way is to use the methodinitWhen the package is loaded, instances can be created here. However, according to the execution order of golang, the initialization function of global variables is better than that of the packageinitFunction is executed first, there is no special gap.

Small pit

Remember what I said at the beginning,goThere is a small hole in the use of singleton pattern in the language. If you don’t pay attention to it, it will cause our singleton pattern to be uselessGetInstanceDo you know why all the others start with a lowercase letter?

In golang, the permissions that can be accessed are determined according to the case of the initial letter. Whether the method name, constant, variable name or structure name, if the first letter is uppercase, it can be accessed by other packages; if the first letter is lower case, it can only be used in this package. It can be simply understood that the initial capital is public and the first lowercase is private. heretype singleton struct {If we use uppercase, then the methods we write are meaningless. Other packages can uses := &singleton{}If you create multiple instances, the singleton mode is meaningless, so you must pay attention to it here

summary

This is the end of this article. Here we explain the simplest singleton mode among the 23 modes. Although it is very simple, the simpler it is, the easier it is to make mistakes. Therefore, we must treat everything carefully

Well, that’s the end of this article. My code has been uploaded to GitHub: https://github.com/asong2020/…

Welcome to star

At the end, I’d like to send you a little welfare. Recently, I was reading the book “micro service architecture design mode”. I talked about it very well. I also collected a PDF. If you need it, you can download it by yourself. Access: public official account: DreamWorks [Golang], background reply: [micro service], you can get it.

I have translated a Chinese document of gin, which will be maintained regularly. If necessary, you can download it by replying to [gin] in the background.

I am asong, an ordinary program ape, let me slowly become stronger. I built one myselfgolangExchange group, small partners in need plus mevxI’ll pull you in. Welcome to your attention. See you next time~~~

Go unlocks the singleton pattern of design pattern

Recommended articles in the past:

  • Hand in hand teaching sister to write message queue
  • Explain the context package in detail, it’s enough to read this one!!!
  • It’s enough to read this article (1)
  • Interviewer: have you ever used for range in go? Can you explain the reasons for these problems
  • Learning wire dependency injection, cron timing task is actually so simple!
  • It’s said that you don’t know JWT and swagger yet. I’m not going to eat any more. I’ll come with the practice project
  • If you master these go language features, your level will be improved by N grades (2)
  • Go to realize the multi person chat room, where you want to chat anything you can!!!
  • Grpc practice – learning grpc is that simple
  • RPC practice of go standard library
  • In 2020, the latest gin framework Chinese document asong picked up English again and translated it with heart
  • Several hot loading methods based on gin
  • Boss: this kid can’t use the validator library to verify the data. It has opened ~~~

Recommended Today

Regular expression sharing for checking primes

This regular expression is shown as follows: Regular expressions for checking prime numbers or not To use this positive regular expression, you need to convert the natural number into multiple 1 strings. For example, 2 should be written as “11”, 3 should be written as “111”, 17 should be written as “11111111111”. This kind of […]