Files
playground/cmd/redis-pub-sub/main.go
XuanLee-HEALER df39693dff commit
2025-11-10 15:30:21 +08:00

125 lines
2.8 KiB
Go

package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"time"
"github.com/redis/go-redis/v9"
)
// 定义 Redis 配置和频道名称
const redisAddr = "localhost:6379" // 替换成您的 Redis 地址
const channelName = "stream:10"
// 全局 Redis 客户端
var rdb *redis.Client
// 定义命令行参数
var mode = flag.String("mode", "", "运行模式:必须是 'pub' (发布者) 或 'sub' (订阅者)")
// 初始化 Redis 客户端并检查连接
func initRedis() {
rdb = redis.NewClient(&redis.Options{
Addr: redisAddr,
Password: "", // 您的密码(如果没有则为空)
DB: 7, // 默认 DB
})
ctx := context.Background()
_, err := rdb.Ping(ctx).Result()
if err != nil {
log.Fatalf("无法连接到 Redis (%s): %v", redisAddr, err)
}
fmt.Println("成功连接到 Redis。")
}
// 订阅者逻辑
func runSubscriber() {
fmt.Println("--- 启动订阅者 (Subscriber) 模式 ---")
// 订阅频道
// Subscribes to the given channels.
pubsub := rdb.Subscribe(context.Background(), channelName)
defer pubsub.Close() // 确保在函数退出时关闭连接
// 接收并处理消息
fmt.Printf("已订阅频道: %s。等待消息...\n", channelName)
// 使用 Channel() 方法获取一个 Go Channel 来接收消息
ch := pubsub.Channel()
// 循环接收消息
for msg := range ch {
fmt.Printf("\n--- 收到消息 ---\n")
fmt.Printf("频道 (Channel): %s\n", msg.Channel)
fmt.Printf("消息 (Payload): %s\n", msg.Payload)
fmt.Printf("----------------\n")
// 添加退出逻辑
if msg.Payload == "exit" {
fmt.Println("\n收到 'exit' 消息,退出订阅循环。")
break
}
}
fmt.Println("订阅者程序退出。")
}
// 发布者逻辑
func runPublisher() {
fmt.Println("--- 启动发布者 (Publisher) 模式 ---")
messages := []string{
"Hello Redis Pub/Sub!",
"This is message two from publisher.",
"A third message is here.",
"exit", // 发送退出信号给订阅者
}
ctx := context.Background()
// 循环发布消息
for i, msg := range messages {
// Publish publishes message to channel.
// Result() 返回值是接收到消息的订阅者数量 (int64)
result, err := rdb.Publish(ctx, channelName, msg).Result()
if err != nil {
log.Fatalf("发布消息失败: %v", err)
}
fmt.Printf("发布消息 %d: '%s' 到频道 '%s',有 %d 个订阅者接收。\n",
i+1, msg, channelName, result)
// 每次发送后等待一小段时间
time.Sleep(500 * time.Millisecond)
}
fmt.Println("发布者程序完成。")
}
func main() {
// 解析命令行参数
flag.Parse()
// 检查模式参数
if *mode != "pub" && *mode != "sub" {
fmt.Println("错误:请指定有效的运行模式。")
flag.Usage()
os.Exit(1)
}
// 初始化 Redis
initRedis()
// 根据模式执行相应逻辑
if *mode == "sub" {
runSubscriber()
} else if *mode == "pub" {
runPublisher()
}
}