Go实战--Design Patterns in Golang 之单利模式(Singleton)

前端之家收集整理的这篇文章主要介绍了Go实战--Design Patterns in Golang 之单利模式(Singleton)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

小插曲:

一猎头拉了个几百人的微信群,主要是沈阳、大连从事IT工作的人,以下是某几个时段的聊天截图:




回不去的东北……很多同事都说如果我选择回东北,肯定后悔,用不了多久还会回北京。

生命不止,继续 go go go !!!

golang的基础知识介绍了很多很多了,主要是一些官方package的介绍。
golang的实战也介绍了很多很多了,包括了很多web框架,rest api,操作各种类型的数据库,各种认证方式,等等等。

接下来,就要跟大家一起学习,分享golang中的设计模式了。

PS: 设计模式的重要性不用多说,也是面试官常常问到的问题。但是对于设计模式,更多的是仁者见仁智者见智。要在实际工作中,代码的积累,工程的积累,再进行深度的思考,逐渐形成的一种思维。

Patterns,顾名思义,具有某种重复性规律的方案。Design Patterns,就是设计过程中可以反复使用的、可以解决特定问题的设计方法

当然,是从最普遍,最简单的单利模式入手了。

何为单例

wiki:
In software engineering,the singleton pattern is a software design pattern that restricts the instantiation of a class to one object.

举个栗子:
Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。这就可以使用单例模式来解决该问题。

C++中实现单例:

@H_502_40@class S { public: static S& getInstance() { static S instance; // Guaranteed to be destroyed. // Instantiated on first use. return instance; } private: S() {} // Constructor? (the {} brackets) are needed here. // C++ 03 // ======== // Don't forget to declare these two. You want to make sure they // are unacceptable otherwise you may accidentally get copies of // your singleton appearing. S(S const&); // Don't Implement void operator=(S const&); // Don't implement // C++ 11 // ======= // We can use the better technique of deleting the methods // we don't want. public: S(S const&) = delete; void operator=(S const&) = delete; // Note: Scott Meyers mentions in his Effective Modern // C++ book,that deleted functions should generally // be public as it results in better error messages // due to the compilers behavior to check accessibility // before deleted status };

把构造函数作为私有。

c++实现单例完整栗子:

@H_502_40@#include <Windows.h> #include <iostream> using namespace std; class SingletonClass { public: static SingletonClass* getInstance() { return (!m_instanceSingleton) ? m_instanceSingleton = new SingletonClass : m_instanceSingleton; } private: // private constructor and destructor SingletonClass() { cout << "SingletonClass instance created!\n"; } ~SingletonClass() {} // private copy constructor and assignment operator SingletonClass(const SingletonClass&); SingletonClass& operator=(const SingletonClass&); static SingletonClass *m_instanceSingleton; }; SingletonClass* SingletonClass::m_instanceSingleton = nullptr; int main(int argc,const char * argv[]) { SingletonClass *singleton; singleton = singleton->getInstance(); cout << singleton << endl; // Another object gets the reference of the first object! SingletonClass *anotherSingleton; anotherSingleton = anotherSingleton->getInstance(); cout << anotherSingleton << endl; Sleep(5000); return 0; }

golang中的单例

但是,在golang的世界中,没有private public static等关键字,也没有面向对象中类的概念。

那么golang是如何控制访问范围的呢?
首字母大写,代表对外部可见,首字母小写代表对外部不可见,适用于所有对象,包括函数方法

golang中全局变量
可以使用全局变量,达到c++中static的效果

golang标准库中的单例模式使用示例
golang是开源的,当我们不知道怎么写代码的时候,完全可以读一读golang的源码。
对于单例模式,例如net/http包中的 http.DefaultClient 和 http.DefaultServeMux。

  • http.DefaultClient
@H_502_40@type Client struct { Transport RoundTripper CheckRedirect func(req *Request,via []*Request) error Jar CookieJar Timeout time.Duration } var DefaultClient = &Client{}
  • http.DefaultServeMux
@H_502_40@// DefaultServeMux is the default ServeMux used by Serve. var DefaultServeMux = &defaultServeMux

golang中单例实现(不完美)
先看代码

@H_502_40@package singleton type single struct { O interface{}; } var instantiated *single = nil func New() *single { if instantiated == nil { instantiated = new(single); } return instantiated; }

看似不错,但是不是线程安全的。

golang中线程安全的单例模式

使用了sync包:
func (*Once) Do

@H_502_40@func (o *Once) Do(f func())

Do calls the function f if and only if Do is being called for the first time for this instance of Once

@H_502_40@package singleton import "sync" type single struct { O interface{}; } var instantiated *single var once sync.Once func New() *single { once.Do(func() { instantiated = &single{} }) return instantiated }

单例模式操作数据库

@H_502_40@package db import "fmt" type repository struct { items map[string]string mu sync.RWMutex } func (r *repository) Set(key,data string) { r.mu.Lock() defer r.mu.Unlock() r.items[key] = data } func (r *repository) Get(key string) (string,error) { r.mu.RLock() defer r.mu.RUnlock() item,ok := r.items[key] if !ok { return "",fmt.Errorf("The '%s' is not presented",key) } return item,nil } var ( r *repository once sync.Once ) func Repository() *repository { once.Do(func() { r = &repository{ items: make(map[string]string),} }) return r }

参考:
http://blog.ralch.com/tutorial/design-patterns/golang-singleton/

猜你在找的Go相关文章