用Go语言理解单例设计模式

Go 语言单例模式详解

单例模式是一种常见的设计模式,确保一个类只有一个实例,并提供全局访问点获取该实例。在 Go 语言中,可通过饱汉式和饿汉式实现单例模式,以下为详细介绍。

一、饿汉式单例模式

1. 实现原理

饿汉式单例模式在程序启动时就创建单例实例,无论是否使用该实例。其优点是实现简单且线程安全,缺点是可能造成资源浪费,因为即使实例未被使用,也会在启动时创建。

2. 代码示例

go 复制代码
package main

import "fmt"

// Singleton 定义单例结构体
type Singleton struct{}

// instance 全局单例实例,在包初始化时就创建
var instance = &Singleton{}

// GetInstance 获取单例实例的函数
func GetInstance() *Singleton {
	return instance
}

func main() {
	s1 := GetInstance()
	s2 := GetInstance()

	if s1 == s2 {
		fmt.Println("两个实例是相同的,单例模式生效")
	} else {
		fmt.Println("单例模式未生效")
	}
}
    

在上述代码中,instance 变量在包初始化时创建,GetInstance 函数直接返回该实例。

二、饱汉式单例模式

1. 实现原理

饱汉式单例模式在第一次使用时才创建单例实例,避免不必要的资源浪费。在多线程环境下,需考虑线程安全,确保实例仅创建一次。Go 语言中可使用 sync.Once 实现线程安全的饱汉式单例模式。

2. 代码示例

go 复制代码
package main

import (
	"fmt"
	"sync"
)

// Singleton 定义单例结构体
type Singleton struct{}

// instance 全局单例实例,初始值为 nil
var instance *Singleton
var once sync.Once

// GetInstance 获取单例实例的函数
func GetInstance() *Singleton {
	once.Do(func() {
		instance = &Singleton{}
	})
	return instance
}

func main() {
	s1 := GetInstance()
	s2 := GetInstance()

	if s1 == s2 {
		fmt.Println("两个实例是相同的,单例模式生效")
	} else {
		fmt.Println("单例模式未生效")
	}
}
    

once.Do 方法确保传入的函数只执行一次,保证 instance 仅创建一次,实现线程安全的饱汉式单例模式。

三、单例结构体中的字段参数

单例结构体的字段参数用于存储和管理单例实例的状态信息,以下结合饿汉式和饱汉式介绍使用方法。

1. 饿汉式单例模式下的字段参数

go 复制代码
package main

import "fmt"

// Config 单例结构体,包含应用程序的配置信息
type Config struct {
    AppName string
    Version string
}

// instance 全局单例实例,在包初始化时就创建
var instance = &Config{
    AppName: "MyApp",
    Version: "1.0.0",
}

// GetInstance 获取单例实例的函数
func GetInstance() *Config {
    return instance
}

func main() {
    config := GetInstance()
    fmt.Printf("App Name: %s, Version: %s\n", config.AppName, config.Version)
}
    

Config 结构体包含 AppNameVersion 字段,包初始化时创建 instance 并初始化字段,通过 GetInstance 函数获取实例并访问字段。

2. 饱汉式单例模式下的字段参数

go 复制代码
package main

import (
    "fmt"
    "sync"
)

// Config 单例结构体,包含应用程序的配置信息
type Config struct {
    AppName string
    Version string
}

// instance 全局单例实例,初始值为 nil
var instance *Config
var once sync.Once

// GetInstance 获取单例实例的函数
func GetInstance() *Config {
    once.Do(func() {
        instance = &Config{
            AppName: "MyApp",
            Version: "1.0.0",
        }
    })
    return instance
}

func main() {
    config := GetInstance()
    fmt.Printf("App Name: %s, Version: %s\n", config.AppName, config.Version)
}
    

once.Do 确保 Config 实例仅创建一次,并初始化 AppNameVersion 字段,通过 GetInstance 函数获取实例并访问字段。

3. 修改单例结构体字段

单例结构体字段可在获取实例后修改,但多协程环境下需注意并发安全,建议使用同步机制(如互斥锁 sync.Mutex)。

go 复制代码
package main

import (
    "fmt"
    "sync"
)

// Config 单例结构体,包含应用程序的配置信息
type Config struct {
    AppName string
    Version string
    Mutex   sync.Mutex
}

// instance 全局单例实例,初始值为 nil
var instance *Config
var once sync.Once

// GetInstance 获取单例实例的函数
func GetInstance() *Config {
    once.Do(func() {
        instance = &Config{
            AppName: "MyApp",
            Version: "1.0.0",
        }
    })
    return instance
}

// UpdateVersion 更新单例结构体中 Version 字段的函数
func (c *Config) UpdateVersion(newVersion string) {
    c.Mutex.Lock()
    defer c.Mutex.Unlock()
    c.Version = newVersion
}

func main() {
    config := GetInstance()
    fmt.Printf("Before update - App Name: %s, Version: %s\n", config.AppName, config.Version)

    config.UpdateVersion("2.0.0")
    fmt.Printf("After update - App Name: %s, Version: %s\n", config.AppName, config.Version)
}
    

Config 结构体添加 Mutex 字段用于并发控制,UpdateVersion 方法修改 Version 字段时先加锁后解锁,确保线程安全。

相关推荐
大飞pkz12 分钟前
【设计模式】代理模式
开发语言·设计模式·c#·代理模式
hans汉斯15 分钟前
【人工智能与机器人研究】一种库坝系统水下成像探查有缆机器人系统设计模式
大数据·数据库·论文阅读·人工智能·设计模式·机器人·论文笔记
LoveXming40 分钟前
Chapter9—享元模式
java·c++·设计模式·享元模式·开闭原则
charlie1145141913 小时前
精读C++20设计模式——结构型设计模式:代理模式
c++·学习·设计模式·代理模式·c++20·概论
lypzcgf9 小时前
Coze源码分析-资源库-删除数据库-后端源码-领域服务/数据访问层
数据库·go·coze·coze源码分析·智能体平台·ai应用平台·agent平台
星空寻流年16 小时前
设计模式第五章(门面模式)
android·设计模式
大飞pkz18 小时前
【设计模式】策略模式
开发语言·设计模式·c#·策略模式
yujkss18 小时前
23种设计模式之【状态机模式】-核心原理与 Java实践
java·ui·设计模式
bkspiderx1 天前
C++设计模式之行为型模式:职责链模式(Chain of Responsibility)
c++·设计模式·责任链模式
青草地溪水旁1 天前
设计模式(C++)详解——迭代器模式(4)
c++·设计模式·迭代器模式