小插曲:
一猎头拉了个几百人的微信群,主要是沈阳、大连从事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
- http.DefaultServeMux
golang中单例实现(不完美)
先看代码:
看似不错,但是不是线程安全的。
golang中线程安全的单例模式
使用了sync包:
func (*Once) Do
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/