go redis作为客户端使用,使用其中的连接池等,可以参考如下例子
package main
import (
"bufio"
"context"
"fmt"
playcardtensflow "go-zero-examples/goredis/api"
"log"
"net"
"strconv"
"strings"
"sync/atomic"
"time"
"github.com/go-redis/redis/v8"
"github.com/golang/protobuf/proto"
)
var ctx = context.Background()
var timeout time.Duration = 0
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "192.168.148.53:6379",
Password: "", // no password set
DB: 0, // use default DB
Network: "tcp",
//连接池容量及闲置连接数量
PoolSize: 15, // 连接池最大socket连接数,默认为4倍CPU数, 4 * runtime.NumCPU
MinIdleConns: 10, //在启动阶段创建指定数量的Idle连接,并长期维持idle状态的连接数不少于指定数量;。
//超时
DialTimeout: 5 * time.Second, //连接建立超时时间,默认5秒。
ReadTimeout: 3 * time.Second, //读超时,默认3秒, -1表示取消读超时
WriteTimeout: 3 * time.Second, //写超时,默认等于读超时
PoolTimeout: 4 * time.Second, //当所有连接都处在繁忙状态时,客户端等待可用连接的最大等待时长,默认为读超时+1秒。
//闲置连接检查包括IdleTimeout,MaxConnAge
IdleCheckFrequency: 60 * time.Second, //闲置连接检查的周期,默认为1分钟,-1表示不做周期性检查,只在客户端获取连接时对闲置连接进行处理。
IdleTimeout: 5 * time.Minute, //闲置超时,默认5分钟,-1表示取消闲置超时检查
MaxConnAge: 0 * time.Second, //连接存活时长,从创建开始计时,超过指定时长则关闭连接,默认为0,即不关闭存活时长较长的连接
//命令执行失败时的重试策略
MaxRetries: 0, // 命令执行失败时,最多重试多少次,默认为0即不重试
MinRetryBackoff: 8 * time.Millisecond, //每次计算重试间隔时间的下限,默认8毫秒,-1表示取消间隔
MaxRetryBackoff: 512 * time.Millisecond, //每次计算重试间隔时间的上限,默认512毫秒,-1表示取消间隔
Dialer: func(ctx context.Context, network string, addr string) (net.Conn, error) {
netDialer := &net.Dialer{
Timeout: 5 * time.Second,
KeepAlive: 5 * time.Minute,
}
return netDialer.Dial(network, addr)
},
//钩子函数
OnConnect: func(ctx context.Context, conn *redis.Conn) error { //仅当客户端执行命令时需要从连接池获取连接时,如果连接池需要新建连接时则会调用此钩子函数
fmt.Printf("conn=%v\n", conn)
return nil
},
// 版权声明:本文为CSDN博主「pengpengzhou」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
// 原文链接:https://blog.csdn.net/pengpengzhou/article/details/105385666
})
pong, err := rdb.Ping(ctx).Result()
if err != nil {
fmt.Println("reis 连接失败:", pong, err)
return
}
fmt.Println("reis 连接成功:", pong)
playcard := &playcardtensflow.ReqPlayCardinfo{
PlayerPosition: 1,
PlayerHandCards: "1,2,3,4,45,5",
PlayerHandSuits: "1,2,3,4,45,5",
NumCardsLeft: "27,27,27,27",
LastPlayedCards: "0,0,0",
RemainCards: "1,2,3,4,45,5,1,2,3,4,45,5,1,2,3,4,45,5",
IsController: true,
Level: 2,
PlayerHandSuitshuase: "1,1,1,1,1",
}
data, err := proto.Marshal(playcard)
if err != nil {
log.Fatal("marshaling error: ", err)
}
fmt.Println("data = ", string(data))
value := "pbconverttostring"
len := len(value)
fmt.Println("value length=", len)
gameid := "30008003"
err = rdb.Set(ctx, gameid, data, timeout).Err()
if err != nil {
panic(err)
}
val, err := rdb.Get(ctx, gameid).Result()
if err != nil {
panic(err)
}
var playcardinfo playcardtensflow.ReqPlayCardinfo
err = proto.Unmarshal([]byte(val), &playcardinfo)
if err != nil {
fmt.Println(gameid, err)
}
fmt.Println(gameid, playcardinfo)
val2, err := rdb.Get(ctx, "key2").Result()
if err == redis.Nil {
fmt.Println("key2 does not exist")
} else if err != nil {
panic(err)
} else {
fmt.Println("key2", val2)
}
// Output: key value
// key2 does not exist
//xiedeju
err = rdb.Set(ctx, "age", "20", 1*time.Second).Err()
if err != nil {
panic(err)
}
rdb.Incr(ctx, "age") // 自增
rdb.Incr(ctx, "age") // 自增
rdb.Decr(ctx, "age") // 自减
val, err = rdb.Get(ctx, "age").Result()
if err != nil {
panic(err)
}
fmt.Println("age", val) // age 的值为21
rdb.Expire(ctx, "age", 10*time.Second)
//redis list
err = rdb.RPush(ctx, "fruit", "2222").Err()
err = rdb.LPush(ctx, "fruit", "Apple").Err()
if err != nil {
panic(err)
}
fmt.Println("age: ", value)
length, err := rdb.LLen(ctx, "fruit").Result() //返回名称为 fruit 的list的长度
if err != nil {
panic(err)
}
fmt.Println("length: ", length) // 长度为2
value, err = rdb.LPop(ctx, "fruit").Result() //返回并删除名称为 fruit 的list中的首元素
if err != nil {
panic(err)
}
fmt.Println("fruit: ", value)
value, err = rdb.RPop(ctx, "fruit").Result() // 返回并删除名称为 fruit 的list中的尾元素
if err != nil {
panic(err)
}
rdb.RPush(ctx, "fruit", "12222").Err()
rdb.RPush(ctx, "fruit", "32222").Err()
rdb.RPush(ctx, "fruit", "32222").Err()
rdb.RPush(ctx, "fruit", "42222").Err()
length, err = rdb.LLen(ctx, "fruit").Result() //返回名称为 fruit 的list的长度
if err != nil {
panic(err)
}
fmt.Println("length: ", length)
rdb.LRange(ctx, "fruit", 0, length)
//fmt.Println("LRange value: ", valueStringSlice.Val())
valueStringSlice1 := rdb.LIndex(ctx, "fruit", 1)
fmt.Println("LIndex value: ", valueStringSlice1.Val())
//redis set
setValue := rdb.SAdd(ctx, "setTest", "set1")
setValue = rdb.SAdd(ctx, "setTest", "set2")
setValue = rdb.SAdd(ctx, "setTest", "set3")
setValue = rdb.SAdd(ctx, "setTest", "set4")
setValue = rdb.SAdd(ctx, "setTest", "set5")
fmt.Println("setValue SAdd: ", setValue.Val())
valuemem := rdb.SMembers(ctx, "setTest")
fmt.Println("SMembers valuemem: ", valuemem.Val())
bValue := rdb.SIsMember(ctx, "setTest", "set25")
fmt.Println("SIsMember bValue: ", bValue.Val())
//redis hash
rdb.HSet(ctx, "user_xys", "name", "xys") // 向名称为 user_xys 的 hash 中添加元素 name
rdb.HSet(ctx, "user_xys", "age", "18") // 向名称为 user_xys 的 hash 中添加元素 age
// 批量地向名称为 user_test 的 hash 中添加元素 name 和 age
rdb.HMSet(ctx, "user_test", map[string]string{"name": "test", "age": "20"})
// 批量获取名为 user_test 的 hash 中的指定字段的值.
fields, err := rdb.HMGet(ctx, "user_test", "name", "age").Result()
if err != nil {
panic(err)
}
fmt.Println("fields in user_test: ", fields)
// 获取名为 user_xys 的 hash 中的字段个数
valength, err := rdb.HLen(ctx, "user_xys").Result()
if err != nil {
panic(err)
}
fmt.Println("field count in user_xys: ", valength) // 字段个数为2
// 删除名为 user_test 的 age 字段
// rdb.HDel(ctx, "user_test", "age")
// age, err := rdb.HGet(ctx, "user_test", "age").Result()
// if err != nil {
// fmt.Printf("Get user_test age error: %v\n", err)
// } else {
// fmt.Println("user_test age is: ", age) // 字段个数为2
// }
//redis hash
rdb.HSet(ctx, "hashtest", "hTest", 12)
rdb.HIncrBy(ctx, "hashtest", "hTest", 12)
hVal := rdb.HVals(ctx, "hashtest")
fmt.Printf("hashTest hVal:%v\n", hVal.Val())
bhash := rdb.HExists(ctx, "hashtest", "hTest")
fmt.Printf("hashTest :%v\n", bhash.Val())
//redis ZStore
zsetVal := rdb.ZAdd(ctx, "zset", &redis.Z{2.5, "tizi"})
fmt.Println("Zset zadd=", zsetVal.Val())
zsetVal = rdb.ZAdd(ctx, "zset", &redis.Z{2.5, "test"})
for i := 0; i < 10000; i++ {
zsetVal = rdb.ZAdd(ctx, "zset", &redis.Z{float64(i) + 2.5, "test" + strconv.Itoa(i*i*10000+55)})
}
fmt.Println("Zset zadd=", zsetVal.Val())
rdb.ZIncr(ctx, "zset", &redis.Z{3.5, "tizi"})
zsetVal = rdb.ZCount(ctx, "zset", "1", "10")
fmt.Println("Zset ZCount=", zsetVal.Val())
zsetVal = rdb.ZCard(ctx, "zset")
fmt.Println("Zset ZCard=", zsetVal.Val())
zsetVal = rdb.ZRemRangeByScore(ctx, "zset", "1", "10000")
fmt.Println("Zset ZRemRangeByScore=", zsetVal.Val())
zsetVal = rdb.ZRemRangeByRank(ctx, "zset", 1, 10000)
fmt.Println("Zset ZRemRangeByRank=", zsetVal.Val())
zsetVal = rdb.ZRemRangeByLex(ctx, "zset", "1", "10000")
fmt.Println("Zset ZRemRangeByLex=", zsetVal.Val())
op := redis.ZRangeBy{
Min: "2", // 最小分数
Max: "100000", // 最大分数
Offset: 0, // 类似sql的limit, 表示开始偏移量
Count: 5, // 一次返回多少数据
}
vals, err := rdb.ZRangeByScoreWithScores(ctx, "zset", &op).Result()
if err != nil {
panic(err)
}
for _, val := range vals {
fmt.Println("value member=", val.Member) // 集合元素
fmt.Println("value score=", val.Score) // 分数
}
// zremval := rdb.ZRem(ctx, "zset", "test")
// fmt.Println("zremval=", zremval.Val())
var vals_test uint32 = 20
newVal := atomic.AddUint32(&vals_test, 5)
fmt.Println("atomic new val=", newVal)
bcas := atomic.CompareAndSwapUint32(&vals_test, vals_test, 30)
fmt.Println("atomic CompareAndSwapUint32 vals_test=", vals_test, ",bcas=", bcas)
rednum := -3
newVal = atomic.AddUint32(&vals_test, uint32(rednum))
fmt.Println("atomic new val rednum =", newVal)
loadval := atomic.LoadUint32(&vals_test)
fmt.Println("atomic loadval=", loadval)
atomic.StoreUint32(&vals_test, 18)
fmt.Println("atomic StoreUint32=", vals_test)
//string test
var strbuild strings.Builder
strbuild.Grow(100)
str := "this is a test for string build"
strlength, strerr := strbuild.WriteString(str)
if strerr != nil {
fmt.Printf("strings.WriteString error =%v", strerr)
}
fmt.Printf("string length =%v\n", strlength)
var reader1 strings.Reader
unreadlen, _ := reader1.Read([]byte(str))
fmt.Printf("unreadlen=%v\n", unreadlen)
readlen := reader1.Len()
readsize := reader1.Size()
fmt.Printf("unreadlen=%v\n", readlen)
fmt.Printf("readsize=%v\n", readsize)
bufread := bufio.NewReader(strings.NewReader(str))
n, _ := bufread.Read([]byte(str))
fmt.Printf("bufio.NewReader=%v\n", n)
}
协议:
syntax="proto3";
package playcardtensflow;
option go_package = "RobotServer/api/playcardtensflow/v1;v1";
option java_multiple_files = true;
option java_outer_classname = "playcardtensflowProtoV1";
message ReqPlayCardinfo
{
int32 player_position = 1;
string player_hand_cards = 2;
string player_hand_suits = 3;
string num_cards_left = 4;
string last_played_cards=5;
string remain_cards =6;
bool is_controller =7;
int32 level = 8;
string player_hand_suitshuase=9;//手牌数值对应的花色
}
//index actionspace中index
//suits 红桃以0表示,黑桃1,方块2,梅花3
message FlushInfo
{
string index = 1;
int32 suits = 2; //
}
message RespPlayCardInfo
{
int32 actionIndex = 1;
int32 player_position=2;
}
service playcardtensflowService {
rpc SendPlayCardToServer (ReqPlayCardinfo) returns (RespPlayCardInfo);
}