go设计模式——单例模式

概念

单例是一种创建型设计模式,它确保一个类在整个程序运行期间只有一个实例 ,并提供一个全局访问点来使用该实例。虽然单例模式在某些情况下非常有用,例如管理全局配置、日志记录或资源共享,但它也带来了与全局变量相似的问题。具体来说,单例模式可能导致代码的模块化和可测试性下降,因为它在整个系统中引入了隐式依赖,使得代码难以解耦和扩展。因此,尽管单例模式可以简化某些设计,但在使用时需要谨慎,以避免对代码的灵活性和可维护性产生不良影响。

demo1

单例模式grpc的连接

bash 复制代码
package client

import (
	"log"
	"sync"
	"google.golang.org/grpc"
	"your/proto/package/path/example" // 更新为你的 proto 包路径
)

type GRPCClient struct {
	conn   *grpc.ClientConn
	client example.ExampleServiceClient
	mu     sync.Mutex
}

var instance *GRPCClient
var once sync.Once

// GetGRPCClient 返回 ExampleServiceClient 的单例实例
func GetGRPCClient() *GRPCClient {
	once.Do(func() {
		instance = &GRPCClient{}
	})

	// 获取锁来保护连接状态检查
	instance.mu.Lock()
	defer instance.mu.Unlock()

	// 如果连接为空或已关闭,则重新建立连接
	if instance.conn == nil || instance.conn.GetState() == grpc.Shutdown {
		conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
		if err != nil {
			log.Fatalf("Failed to connect to gRPC server: %v", err)
		}
		instance.conn = conn
		instance.client = example.NewExampleServiceClient(conn)
	}

	return instance
}

// GetClient 返回 gRPC 客户端
func (g *GRPCClient) GetClient() example.ExampleServiceClient {
	return g.client
}

// CloseConnection 关闭 gRPC 连接
func (g *GRPCClient) CloseConnection() error {
	g.mu.Lock()
	defer g.mu.Unlock()

	if g.conn != nil {
		err := g.conn.Close()
		g.conn = nil // 重置连接,确保下一次调用时可以重新连接
		return err
	}
	return nil
}

demo1

你想要在程序中创建一个"月亮"对象,并确保在整个程序运行期间,只有一个这样的"月亮"对象存在。这个对象应该是私有的,不可以被其他地方直接访问或修改。就是我们的desc是不允许外部修改的

bash 复制代码
package singleton

import "sync"

// sync.Once 确保月亮单例实例只会被创建一次
var once sync.Once

// moon 是一个不可导出的结构体
type moon struct {
	description string
}

func (m *moon) String() string {
	return m.description
}

// theMoon 是 moon 类型的单例实例
var theMoon *moon

// TheMoon 返回月亮单例实例
func TheMoon() *moon {
	// 使用 sync.Once 确保 theMoon 只会被初始化一次
	once.Do(func() {
		theMoon = &moon{
			description: "美丽的月亮,照亮夜空。",
		}
	})
	return theMoon
}
使用场景

1. 全局配置管理

• 在应用程序中,配置通常是全局的,且不希望在多个地方加载配置文件。使用单例模式可以确保配置文件只被加载一次,并在应用程序的整个生命周期内共享同一个配置实例。

2. 日志记录

• 日志记录器通常需要在应用程序的不同部分被调用,但希望所有日志都通过同一个实例处理,以便统一管理日志的输出目标、格式等。单例模式可以保证只有一个日志记录器实例在整个程序中被使用。

3. 数据库连接池

• 数据库连接是一个昂贵的资源,通常希望应用程序共享一个连接池来管理数据库连接。通过单例模式,可以确保连接池实例在整个应用程序中是唯一的,并且被多个客户端共享。

4. 缓存管理

• 在一些应用中,缓存管理通常需要一个全局的管理对象来管理缓存数据。单例模式可以用于确保缓存管理对象在应用中只有一个实例,从而避免多次实例化带来的资源浪费。

5. 线程池

• 在并发编程中,线程池用于管理线程的复用,以避免频繁创建和销毁线程带来的开销。通过单例模式,可以确保线程池在整个应用中只有一个实例,并为所有任务共享。

6. 设备或资源管理

• 一些应用需要管理有限的设备或资源,如打印机、显卡等。这些设备通常不希望被多个实例同时控制,因此可以使用单例模式确保对设备的管理是通过单一实例完成的。

相关推荐
raindayinrain7 小时前
c++设计模式
开发语言·c++·设计模式
工一木子7 小时前
设计模式与生活⑦:你打的车,隔着一个平台
设计模式
电子科技圈8 小时前
2026 RISC-V中国峰会观察:编译调试工具链的“在场节奏”,释放了什么信号?
大数据·人工智能·设计模式·软件工程·软件构建·代码规范·risc-v
紧跟先前的步伐8 小时前
Go AI Agent 实战 22|完善 Agent 执行循环:从工具调用到最终回答
人工智能·ai·golang
电子科技圈9 小时前
Arm电机控制开发工具哪家强?
arm开发·单片机·嵌入式硬件·设计模式·软件构建
后台模板学习9 小时前
Go Web开发中任务调度框架的源码解析与高可用实现方案
开发语言·后端·golang
FungLeo9 小时前
成为全栈·Go 后端篇·分类树与标签关系:目录变更为何需要协调
golang·go·gorm·数据库事务·分类树·成为全栈
fly-iot10 小时前
【FDE知识库】(1):AI 编程时代开发语言选型分析,云使用go,企业用java,算法python,底层c
开发语言·人工智能·golang
FungLeo10 小时前
成为全栈·Go 后端篇·文章查询与展示投影:安全分页、排序和软删除
golang·go·gorm·分页查询·成为全栈·sql安全
紧跟先前的步伐19 小时前
Go AI Agent 实战 24|工具系统工程化收尾与阶段验收
人工智能·ai·golang·1024程序员节