游戏ID统一管理器DEMO

一般游戏的角色ID、名字,工会ID、名字,等最好统一创建,方便合服处理,可以以此基础,动态配置生成ID

这个也可以用openresty 作个,可能更专业点,

1:go1.20+ 最后一版支持win7的

mongodb v7.0.9

Redis v=7.2.4

2:代码

3:代码

go 复制代码
package main

import (
	"fmt"
	"generateid/config"
	"generateid/httpserver"
	"generateid/mongodb"
	"generateid/redis"
	"github.com/rs/zerolog/log"
	"net"
	"os"
	"os/signal"
	"runtime"
	"syscall"
)

func main() {
	err := config.LoadConfig("config/generateuid.yaml")
	if err != nil {
		log.Error().Msgf("err: %v", err)
		os.Exit(0)
	}
	if err1 := mongodb.InitMongo(); err1 != nil {
		os.Exit(10)
	}
	if err2 := redis.InitRedis(); err2 != nil {
		os.Exit(10)
	}
	lis := httpserver.SetUpHttpServer(config.GetListenIpPort(), int32(config.GetListenMaxConn()), config.GetMd5Salt(), config.GetServerMOde())
	//exit
	sysType := runtime.GOOS
	if sysType == "windows" {
		winCheckExit(lis)
	} else if sysType == "linux" {
		linuxCheckExit(lis)
	}

}

func winCheckExit(lis net.Listener) {
	quitchan := make(chan struct{})
	go func() {
		<-quitchan
		fmt.Println("generateid server close")
		lis.Close()
	}()
	fmt.Println("generateid server setup")
	for {
		var strinput string
		fmt.Scan(&strinput)
		if strinput == "quit" {
			quitchan <- struct{}{}
		} else if strinput == "help" {
			fmt.Println("input quit to quit progress \n")
		}
	}
}

func linuxCheckExit(lis net.Listener) {
	quitchan := make(chan os.Signal)
	signal.Notify(quitchan,
		//	syscall.SIGINT, //ctrl+c
		syscall.SIGINT, //ctrl+/
		syscall.SIGTERM,
		syscall.SIGHUP, //终端结束
	)
	exitfun := func() {
		fmt.Println("generateid server close")
		lis.Close()
		//os.Exit(10)
	}
	for s := range quitchan {
		switch s {
		case syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT: //syscall.SIGHUP,
			fmt.Println("Program Exit...", s)
			exitfun()
		default:
			fmt.Println("other signal", s)
		}
	}
}
go 复制代码
package httpserver

import (
	"context"
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	gdef "generateid/gobaldefine"
	"generateid/mongodb"
	"go.mongodb.org/mongo-driver/bson"
	"log"
	"net/http"
	"reflect"
	"regexp"
	"strconv"
	"sync/atomic"
	"time"

	//	"sync"
	"encoding/json"
	"fmt"
	redis2 "generateid/redis"
	"golang.org/x/net/netutil"
	"net"
)

type HttpServer struct {
	//curnum  int32
	maxnum    int32
	debugmode bool
	md5salt   string

	maxcurrentuserid   uint32 //角色当前最大ID
	maxcurrentfamilyid uint32 //工会当前最大ID
}

func (self *HttpServer) GetValidUserId() uint32 {
	return atomic.AddUint32(&self.maxcurrentuserid, 1)
}

func (self *HttpServer) GetValidFamilyId() uint32 {
	return atomic.AddUint32(&self.maxcurrentfamilyid, 1)
}

func (self *HttpServer) SetUserId(uid uint32) {
	atomic.StoreUint32(&self.maxcurrentuserid, uid)
}
func (self *HttpServer) SetFamilyId(uid uint32) {
	atomic.StoreUint32(&self.maxcurrentfamilyid, uid)
}

var (
	httpser HttpServer
)

func GetHttpSerInstance() *HttpServer {
	return &httpser
}

const (
	SUCESS_GENERATE_NAME = 1  //User_UID 作为name
	ERROR_NONE           = 0  //没错误  成功的 OK的
	ERROR_NAME_INVALIDL  = -1 //名字有非法字符或重名或长度不对
	ERROR_NAME_DUPLICATE = -2 //重名
	ERROR_HANDSHAKE_KEY  = -3 //握手码错误
	ERROR_TIME_INVALIDL  = -4 // 超时

	ERROR_OTHER = -15 //其他错误
)

//return map[string]interface{}{
//"uname": name,
//"md5":   md5v,
//"sid":   sid,
//"st":    st,
//}

type JsonGenerateUidReq struct {
	UName string `json:"uname"`
	Md5v  string `json:"md5"`
	Sid   uint32 `json:"sid"`
	Stime int64  `json:"st"`
}

// 统一回复的
type JsonGenerateUidResult struct {
	Result int32  `json:"result"` // < 0  错误 -1 名字有非法字符或重名或长度不对  -2 握手码错误 -15 其他错误 >=0 OK 下面的有效
	Uid    uint32 `json:"uid"`
	Name   string `json:"name"`
}

//maxcurrentuserid  uint32		//角色当前最大ID
//maxcurrentfamilyid uint32//工会当前最大ID

// 得到client  ip
func RetmoteIp(r *http.Request) string {
	remoteaddr := r.RemoteAddr
	if ip := r.Header.Get("Remote_addr"); ip != "" {
		remoteaddr = ip
	} else {
		remoteaddr, _, _ = net.SplitHostPort(remoteaddr)
	}
	if remoteaddr == "::1" {
		remoteaddr = "127.0.0.1"
	}
	return remoteaddr
}

func getMd5Salt() string {
	return httpser.md5salt
}

func isDebugMode() bool {
	return httpser.debugmode
}

// 设置跨域
func setkuayu(pw http.ResponseWriter) {
	//设置跨域访问 nodejs
	/*app.all('*', function(req, res, next) {
		res.header("Access-Control-Allow-Origin", "*");
		res.header("Access-Control-Allow-Headers", "X-Requested-With");
		res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
		res.header("X-Powered-By",' 3.2.1')
		res.header("Content-Type", "application/json;charset=utf-8");
		next();
	});
	*/
	//(原因:CORS 头 'Access-Control-Allow-Origin' 不匹配 '*, Content-Type')
	pw.Header().Set("Access-Control-Allow-Origin", "*")
	pw.Header().Add("Access-Control-Allow-Headers", "Content-Type")
	pw.Header().Set("Content-Type", "application/json;charset=utf-8")
}

// 发送json 数据
func sendJson(w http.ResponseWriter, v interface{}) bool {

	if data, err := json.Marshal(v); err == nil {
		setkuayu(w)
		fmt.Fprint(w, string(data))
		log.Println(string(data))
		return true
	} else {
		log.Println(err)
		log.Println(v)
		return false
	}
}

func checkstring(str string) bool {
	//	str := "ABc123汉字./"
	//使用regexp.MustCompile函数编译正则表达式^[A-Za-z0-9\u4e00-\u9fa5./]+$,表示字符串只能包含大小写字母、数字、汉字、点和斜杠
	//exp := regexp.MustCompile(`^[A-Za-z0-9\u4e00-\u9fa5./]+$`)
	//exp := regexp.MustCompile(`^[A-Za-z0-9\u4e00-\u9fa5_-]+$`)
	//BASE64URL编码的流程:1、明文使用BASE64进行加密 2、在BASE64的基础上进行一下的编码:2.1)去除尾部的"=" 2.2)把"+"替换成"-" 2.3)把"/"替换成"_"
	//BASE64URL解码的流程:1)把"-"替换成"+". 2)把"_"替换成"/" . 3)(计算BASE64URL编码长度)%4 a)结果为0,不做处理 b)结果为2,字符串添加"==" c)结果为3,字符串添加"="
	exp := regexp.MustCompile(`^[A-Za-z0-9_-]+$`) //base64url
	if exp.MatchString(str) {
		//fmt.Println("字符串匹配成功")
		return true
	} else {
		//fmt.Println("字符串匹配失败")
		return false
	}
}

func GetStringValue(v reflect.Value) string {
	switch v.Kind() {
	case reflect.String:
		return v.String()
	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return fmt.Sprintf("%v", v.Uint())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return fmt.Sprintf("%v", v.Int())
	}
	return ""
}

func geturlparams(r *http.Request) map[string]string {
	//Method specifies the HTTP method (GET, POST, PUT, etc.).
	params := map[string]string{}
	switch r.Method {
	case "GET":
		{
			query := r.URL.Query()
			for k, v := range query {
				params[k] = v[0]
			}
		}
	case "POST":
		{
			// 根据请求body创建一个json解析器实例
			decoder := json.NewDecoder(r.Body)
			// 用于存放参数key=value数据
			// 解析参数 存入map
			//t := make(map[string]interface{})
			//	decoder.Decode(&params)
			ts := &JsonGenerateUidReq{}
			if err := decoder.Decode(ts); err == nil {

				valueOf := reflect.ValueOf(ts) //.Type()
				if valueOf.Kind() == reflect.Pointer || valueOf.Kind() == reflect.Slice {
					valueOf = valueOf.Elem()
				}
				typeOf := reflect.TypeOf(ts)
				if typeOf.Kind() == reflect.Pointer || typeOf.Kind() == reflect.Slice {
					typeOf = typeOf.Elem()
				}

				for i := 0; i < valueOf.NumField(); i++ {
					fieldvalue := valueOf.Field(i)
					fieldtype := typeOf.Field(i)
					jsontag := fieldtype.Tag.Get("json")
					//	log.Printf("k:%v v=%v tag=%v kind=%v v=%v", fieldtype.Name, fieldvalue.Interface(), jsontag, fieldvalue.Kind(), GetStringValue(fieldvalue))

					params[jsontag] = GetStringValue(fieldvalue)
				}
			}

		}
	}
	//return params
	return params
}

//func closeconnect(w http.ResponseWriter) {
//	hj, ok := w.(http.Hijacker)
//	if !ok {
//		http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
//		return
//	}
//	conn, bufrw, err := hj.Hijack()
//	if err != nil {
//		http.Error(w, err.Error(), http.StatusInternalServerError)
//		return
//	}
//	// Don't forget to close the connection:
//	defer conn.Close()
//	conn.SetWriteDeadline(time.Now().Add(10 * time.Second))
//	bufrw.WriteString("Now we're speaking raw TCP. Say hi: ")
//	bufrw.Flush()
//	s, err := bufrw.ReadString('\n')
//	if err != nil {
//		log.Printf("error reading string: %v", err)
//		return
//	}
//	fmt.Fprintf(bufrw, "You said: %q\nBye.\n", s)
//	bufrw.Flush()
//}

// ServeHTTP implements an http.Handler that answers RPC requests.
//func (server *server) servehttp(w http.responsewriter, req *http.request) {
//	if req.method != "connect" {
//		w.header().set("content-type", "text/plain; charset=utf-8")
//		w.writeheader(http.statusmethodnotallowed)
//		io.writestring(w, "405 must connect\n")
//		return
//	}
//	conn, _, err := w.(http.hijacker).hijack()
//	if err != nil {
//		log.print("rpc hijacking ", req.remoteaddr, ": ", err.error())
//		return
//	}
//	io.writestring(conn, "http/1.0 "+connected+"\n\n")
//	server.serveconn(conn)
//}

func errorrep(w http.ResponseWriter, errorcdoe int) {
	w.WriteHeader(errorcdoe)
	w.Write([]byte("error"))
}

func errormsgrep(w http.ResponseWriter, errorcode int32) {
	v := &JsonGenerateUidResult{}
	v.Result = errorcode
	sendJson(w, v)
}

func successrep(w http.ResponseWriter, res int32, uid uint32, name string) {
	v := &JsonGenerateUidResult{}
	v.Result = res
	v.Uid = uid
	v.Name = name
	sendJson(w, v)
}

func GenerateMd5Value(name string, sid uint32, st int64, salt string) string {
	plaintext := fmt.Sprintf("[%v#%v#%v#%v]", name, sid, st, salt)
	m5 := md5.New()
	m5.Write([]byte(plaintext))
	t := hex.EncodeToString(m5.Sum(nil))
	return t
	//by := m5.Sum([]byte(plaintext))
	//if len(by) == 64 {
	//	return fmt.Sprintf("%x", by[16:48]) //32byte
	//}
	//t := fmt.Sprintf("%x", by)
	//return t //string(m5.Sum([]byte(plaintext)))
	//32 get 16 [8:24]
	//64 get 32 [16:48]
}

func doGenerateName(tableindex uint32, w http.ResponseWriter, r *http.Request) {
	params := geturlparams(r)
	remoteip := RetmoteIp(r)
	if len(params) > 0 {
		vname, ok1 := params["uname"]
		//vhandshakekey, ok2 := params["md5"]
		vmd5, ok2 := params["md5"]
		vserverid, ok3 := params["sid"]
		vtime, ok4 := params["st"]
		if ok1 && ok2 && ok3 && ok4 {
			log.Printf("uname=%v md5=%v sid=%v st=%v", vname, vmd5, vserverid, vtime)
			sid, err1 := strconv.Atoi(vserverid)
			st, err2 := strconv.ParseInt(vtime, 10, 64)
			if err1 != nil || err2 != nil {
				log.Printf("ip=%v vserver=%v  name=%v", remoteip, vserverid, vname)
				errormsgrep(w, ERROR_NAME_INVALIDL)
				return
			}
			if vmd5 != GenerateMd5Value(vname, uint32(sid), st, getMd5Salt()) {
				if !isDebugMode() {
					//回复错误
					errormsgrep(w, ERROR_HANDSHAKE_KEY)
					return
				}
			}
			curtime := time.Now().Unix()
			if curtime > st+60 {
				if !isDebugMode() {
					//回复错误
					errormsgrep(w, ERROR_TIME_INVALIDL)
					return
				}
			}
			if len(vname) > 3 && len(vname) <= 64 && checkstring(vname) {
				//合法
				if uid, _ := GenerateName(tableindex, vname, false); uid > 0 {
					successrep(w, ERROR_NONE, uid, vname)
				} else {
					errormsgrep(w, ERROR_NAME_DUPLICATE)
				}

			} else if len(vname) <= 1 { //空
				//合法
				if uid, tanme := GenerateUidOnly(tableindex); uid > 0 {
					successrep(w, SUCESS_GENERATE_NAME, uid, tanme)
				} else {
					errormsgrep(w, ERROR_NAME_DUPLICATE)
				}
			} else {
				log.Printf("ip=%v vserver=%v  name=%v", remoteip, vserverid, vname)
				errormsgrep(w, ERROR_NAME_INVALIDL)
			}
			return
		}
	}
	errorrep(w, 404)
}

func handlerGenerateUserUid(w http.ResponseWriter, r *http.Request) {
	doGenerateName(gdef.TYPE_TABLE_USER, w, r)
}

func handlerGenerateFamilyUid(w http.ResponseWriter, r *http.Request) {
	doGenerateName(gdef.TYPE_TABLE_FAMILY, w, r)
}

//func clientfun(w http.ResponseWriter, r *http.Request) {
//
//	r.ParseForm()
//
//	path := r.URL.Path
//	remoteip := RetmoteIp(r)
//	log.Printf("path =%v remoteip=%v \n", path, remoteip)
//	//strings.Split(r.RemoteAddr,":")
//	switch path {
//	case "/get_serverinfo": //得到服务器版本信息
//		v := &jsondata.Serverinfo{}
//		v.Version = "2017081011"
//		v.State = int32(time.Now().Unix()) //正常
//		sendJson(w, v)
//	case "/login":
//		param_account, f1 := r.Form["account"]
//		param_token, f2 := r.Form["token"]
//		if f1 && f2 && len(param_account[0]) > 1 {
//			doLogin(w, param_account[0], param_token[0], remoteip)
//		}
//	}
//}

func SetUpHttpServer(httpaddr string, maxnum int32, md5salt string, bdebug bool) net.Listener {
	httpser.maxnum = maxnum
	httpser.debugmode = bdebug //true debug  false release  default false
	httpser.md5salt = md5salt  //握手key
	log.Printf("httpaddr:%v maxnum=%v \n", httpaddr, maxnum)

	l, err := net.Listen("tcp", httpaddr)
	if err != nil {
		log.Fatal("listen:", err)
	}
	lis := netutil.LimitListener(l, int(maxnum))
	http.HandleFunc("/uuid", handlerGenerateUserUid)
	http.HandleFunc("/fuid", handlerGenerateFamilyUid)
	
	//先清理下
	ClearCurIndexRedisDb()
	if !QueryMaxUserId() {
		log.Fatal("QueryMaxUserId:")
	}
	QueryAllUserName()
	if !QueryMaxFamilyId() {
		log.Fatal("QueryMaxFamilyId:")
	}
	QueryAllFamilyName()
	/
	go http.Serve(lis, nil)
	//go http.Serve(lis, http.HandlerFunc(clientfun))

	return lis
}

func QueryMaxUserId() bool {
	querytimeout := time.Second * 10 //30秒
	sort := bson.D{{"uid", -1}}
	uid, err := mongodb.GetMongoSyncInstance().FindOneMax(sort, gdef.TABLE_USER_UID, querytimeout)
	if err != nil {
		log.Printf("QueryMaxUserId error=%v", err.Error())
		return false
	}
	log.Printf("QueryMaxUserId(%v)", uid)
	if uid < gdef.BASE_USER_ID {
		uid = gdef.BASE_USER_ID
	}
	GetHttpSerInstance().SetUserId(uid)
	return true
}

func QueryMaxFamilyId() bool {
	querytimeout := time.Second * 10 //30秒
	sort := bson.D{{"uid", -1}}
	uid, err := mongodb.GetMongoSyncInstance().FindOneMax(sort, gdef.TABLE_Family_UID, querytimeout)
	if err != nil {
		log.Printf("QueryMaxFamilyId error=%v", err.Error())
		return false
	}
	log.Printf("QueryMaxFamilyId(%v)", uid)
	if uid < gdef.BASE_FAMILY_ID {
		uid = gdef.BASE_FAMILY_ID
	}
	GetHttpSerInstance().SetFamilyId(uid)
	return true
}

func QueryAllUserName() int64 {
	//如果想指定 <projection> 是包含字段,那所有字段值都得统一是 1,相反如果是不包含,也必须都是 0
	//projection 里要不写1 要么写0 不能混合在里面
	projection := bson.D{
		{"uid", 0},
		//	{"name", 1},
		{"_id", 0},
	}
	//
	mongodb_table := gdef.TABLE_USER_UID
	redis_table := gdef.REDIS_TABLE_USER
	querytimeout := time.Second * 30 //30秒
	cursor, err := mongodb.GetMongoSyncInstance().FindAll(projection, mongodb_table, querytimeout)
	if err != nil {
		return -1
	}
	user := new(gdef.UserInfo)
	rs := redis2.GetRedisSyncClient()
	for cursor.Next(context.Background()) {
		if err = cursor.Decode(user); err != nil {
			return -2
		}
		rs.SAdd_ReturnVoid(redis_table, user.Name)
	}
	totalnum := rs.SCard(redis_table)
	log.Printf("QueryName %v(%v)", mongodb_table, totalnum)

	return totalnum
}

func QueryAllFamilyName() int64 {
	//如果想指定 <projection> 是包含字段,那所有字段值都得统一是 1,相反如果是不包含,也必须都是 0
	//projection 里要不写1 要么写0 不能混合在里面
	projection := bson.D{
		{"uid", 0},
		//	{"name", 1},
		{"_id", 0},
	}
	//
	mongodb_table := gdef.TABLE_Family_UID
	redis_table := gdef.REDIS_TABLE_FAMILY
	querytimeout := time.Second * 30 //30秒
	cursor, err := mongodb.GetMongoSyncInstance().FindAll(projection, mongodb_table, querytimeout)
	if err != nil {
		return -1
	}
	user := new(gdef.FamilyInfo)
	rs := redis2.GetRedisSyncClient()
	for cursor.Next(context.Background()) {
		if err = cursor.Decode(user); err != nil {
			return -2
		}
		rs.SAdd_ReturnVoid(redis_table, user.Name)
	}
	totalnum := rs.SCard(redis_table)
	log.Printf("QueryName %v(%v)", mongodb_table, totalnum)
	return totalnum
}

func CheckNameVaild(name string) bool {
	namelen := len(name)
	if namelen < 3 {
		return false
	}
	//user_  family_
	if (namelen > 5 && name[:5] == "user_") || (namelen > 7 && name[:7] == "family_") {
		return false
	}
	return true
}

func GenerateName(tableindex uint32, name string, bGenerateName bool) (uint32, string) {
	mongodb_table := ""
	redis_table := ""
	//	fGetUid := func() uint32 { return 0 }
	switch tableindex {
	case gdef.TYPE_TABLE_USER:
		mongodb_table = gdef.TABLE_USER_UID
		redis_table = gdef.REDIS_TABLE_USER
	//	fGetUid = GetHttpSerInstance().GetValidUserId
	//	data = &gdef.UserInfo{}
	case gdef.TYPE_TABLE_FAMILY:
		mongodb_table = gdef.TABLE_Family_UID
		redis_table = gdef.REDIS_TABLE_FAMILY
	//	fGetUid = GetHttpSerInstance().GetValidFamilyId
	//	data = &gdef.FamilyInfo{}
	default:
		return 0, ""
	}
	rs := redis2.GetRedisSyncClient()
	mgdb := mongodb.GetMongoSyncInstance()
	if CheckNameVaild(name) {
		nRet := rs.SAdd(redis_table, name)
		switch {
		case nRet < 0:
			return 0, "Error"
		case nRet == 0: //重名了
			return 0, "DuplicateName"
		default: //1 ok
			break
		}
	} else {
		return 0, "Name len error"
	}

	inserttimeout := time.Second * 3 //3秒
	plaintext_name := name           //明文name
	switch tableindex {
	case gdef.TYPE_TABLE_USER:
		uid := GetHttpSerInstance().GetValidUserId()
		//if bGenerateName && len(name) < 3 {
		//	plaintext_name = " user_" + strconv.Itoa(int(uid))
		//	name = base64.URLEncoding.EncodeToString([]byte(plaintext_name))
		//}
		data := &gdef.UserInfo{uid, plaintext_name}
		if _, err := mgdb.InsertData(data, mongodb_table, inserttimeout); err == nil {
			//	rs.SAdd(redis_table, name)
			return uid, name
		}
		rs.SRem(redis_table, name)
	case gdef.TYPE_TABLE_FAMILY:
		uid := GetHttpSerInstance().GetValidFamilyId()
		//if bGenerateName && len(name) < 3 {
		//	plaintext_name = "family_" + strconv.Itoa(int(uid))
		//	name = base64.URLEncoding.EncodeToString([]byte(plaintext_name))
		//}

		data := &gdef.FamilyInfo{uid, plaintext_name}
		if _, err := mgdb.InsertData(data, mongodb_table, inserttimeout); err == nil {
			//rs.SAdd(redis_table, name)
			return uid, name
		} else {
			rs.SRem(redis_table, name)
		}
	}
	return 0, "Errorother"
}

func GenerateUidOnly(tableindex uint32) (uint32, string) {
	mongodb_table := ""
	//	redis_table := ""
	name := ""
	//	fGetUid := func() uint32 { return 0 }
	switch tableindex {
	case gdef.TYPE_TABLE_USER:
		mongodb_table = gdef.TABLE_USER_UID
	//	redis_table = gdef.REDIS_TABLE_USER
	//	fGetUid = GetHttpSerInstance().GetValidUserId
	//	data = &gdef.UserInfo{}
	case gdef.TYPE_TABLE_FAMILY:
		mongodb_table = gdef.TABLE_Family_UID
	//	redis_table = gdef.REDIS_TABLE_FAMILY
	//	fGetUid = GetHttpSerInstance().GetValidFamilyId
	//	data = &gdef.FamilyInfo{}
	default:
		return 0, ""
	}
	//	rs := redis2.GetRedisSyncClient()
	mgdb := mongodb.GetMongoSyncInstance()
	inserttimeout := time.Second * 3 //3秒
	plaintext_name := ""             //明文name
	switch tableindex {
	case gdef.TYPE_TABLE_USER:
		uid := GetHttpSerInstance().GetValidUserId()
		plaintext_name = " user_" + strconv.Itoa(int(uid))
		name = base64.URLEncoding.EncodeToString([]byte(plaintext_name))
		log.Printf("temp return uid(%v) name(%v)", uid, name)
		//return uid, name
		//下面的插入有问题,有时间再修正下
		data := &gdef.UserInfo{uid, plaintext_name}
		if _, err := mgdb.InsertData(data, mongodb_table, inserttimeout); err == nil {
			//rs.SAdd(redis_table, name)
			return uid, name
		} else {
			log.Printf("mgdb.InsertData error=%v", err.Error())
		}
	case gdef.TYPE_TABLE_FAMILY:
		uid := GetHttpSerInstance().GetValidFamilyId()
		plaintext_name = "family_" + strconv.Itoa(int(uid))
		name = base64.URLEncoding.EncodeToString([]byte(plaintext_name))

		data := &gdef.FamilyInfo{uid, plaintext_name}
		if _, err := mgdb.InsertData(data, mongodb_table, inserttimeout); err == nil {
			return uid, name
		}
	}
	return 0, "Errorother"
}

// 清理当前索引的redis DB
func ClearCurIndexRedisDb() {
	redis2.GetRedisSyncClient().FlushDB()
}

/*
//for _, v := range username {
		//	rediscli.SAdd(tableuser, v)
		//}
		//realnum := rediscli.SCard(tableuser).Val()
		//if int64(namecount) != realnum {
		//	log.Fatal("queryallrolename num is equal org=%v read=%v ", namecount, realnum)
		//}
		//doc := cursor.Current
		//doc.Index(0)

		//assert.False(t, containsKey(doc, "_id"))
		//assert.True(t, containsKey(doc, "item"))
		//assert.True(t, containsKey(doc, "status"))
		//assert.False(t, containsKey(doc, "size"))
		//assert.False(t, containsKey(doc, "instock"))
		//for cursor.Next(context.TODO()) {
		//	// A new result variable should be declared for each document.
		//	var result bson.M
		//	if err := cursor.Decode(&result); err != nil {
		//		log.Fatal(err)
		//	}
		//	fmt.Println(result)
		//}
*/

4:测试,这个没什么好测试的,

有空可以找找原来用openresty+mysql做的,

这里的demo工程有需要再上传

如果觉得有用,麻烦点个赞,加个收藏

相关推荐
tyler_download2 小时前
golang 实现比特币内核:处理椭圆曲线中的天文数字
golang·blockchain·bitcoin
Footprint_Analytics2 小时前
Footprint Analytics 助力 Sei 游戏生态增长
游戏·web3·区块链
疯狂的程需猿3 小时前
一个百度、必应搜索引擎图片获取下载的工具包
golang·图搜索
架构师那点事儿3 小时前
golang 用unsafe 无所畏惧,但使用不得到会panic
架构·go·掘金技术征文
明月看潮生4 小时前
青少年编程与数学 02-003 Go语言网络编程 09课题、Cookie
青少年编程·golang·网络编程·编程与数学
明月看潮生5 小时前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
明月看潮生5 小时前
青少年编程与数学 02-003 Go语言网络编程 14课题、Go语言Udp编程
青少年编程·golang·网络编程·编程与数学
半盏茶香6 小时前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
hlsd#6 小时前
go 集成go-redis 缓存操作
redis·缓存·golang
PandaQue13 小时前
《怪物猎人:荒野》游戏可以键鼠直连吗
游戏