package main import ( "flag" "github.com/gin-gonic/gin" "io" "io/ioutil" "log" "os" "os/signal" "syscall" "time" "github.com/RoaringBitmap/roaring" "github.com/cespare/xxhash/v2" ) var ( dbfile = flag.String("dbfile", "./db", "数据库文件") addr = flag.String("p", ":8088", "监听地址") cache = roaring.NewBitmap() cacheModify = false //控制10秒 定时写入文件 ) type ProjectData struct { ProjectName string `json:"project_name"` ProjectCode string `json:"project_code"` Buyer string `json:"buyer"` ProjectDate string `json:"project_date"` Packages string `json:"packages"` } // init 初始化 func init() { flag.Parse() _, err := os.Stat(*dbfile) if !os.IsNotExist(err) { bs, err := ioutil.ReadFile(*dbfile) if err != nil { log.Fatal(err) } if len(bs) > 0 { cache.FromBuffer(bs) } } //监听,写入文件保存 go func() { for { time.Sleep(10 * time.Second) if cacheModify { saveDb() cacheModify = false } } }() } func main() { // 设置 Gin 模式为发布模式,关闭每次路由请求打印 gin.SetMode(gin.ReleaseMode) gin.DefaultWriter = io.Discard router := gin.Default() router.POST("/rename", getRename) log.Println("程序监听端口", *addr) go func() { err := router.Run(*addr) if err != nil { log.Fatal(err) } }() //监听异常退出信号;及时保存数据 signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM) <-signalChan log.Println("程序退出") saveDb() } // saveDb 文件写入 func saveDb() { fo, err := os.OpenFile(*dbfile, os.O_CREATE|os.O_RDWR|os.O_SYNC|os.O_TRUNC, 0777) if err != nil { log.Fatal(err) } defer fo.Close() cache.WriteTo(fo) } // hash 计算hash func hash(src string) uint64 { return xxhash.Sum64String(src) } // RenameProjectName 获取新的不重复的项目名称 func RenameProjectName(projectName, projectCode, packages, projectDate, buyer string) string { //TODO 1.判断项目名称是否重复 var id uint64 defer func() { cache.Add(uint32(id)) cacheModify = true }() //1.项目名称 if projectName != "" { id = hash(projectName) if !cache.Contains(uint32(id)) { return projectName } } //TODO 2.1 项目名称+项目编码 if projectCode != "" { newName := projectName + "_" + projectCode id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 2.2 项目名称+分包信息 if packages != "" { newName := projectName + "_" + packages id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 2.3 项目名称+项目时间 if projectDate != "" { newName := projectName + "_" + projectDate id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 2.4 项目名称+采购单位名称 if buyer != "" { newName := projectName + "_" + buyer id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 3.1 项目名称+项目编码+分包信息 if projectCode != "" && packages != "" { newName := projectName + "_" + projectCode + "_" + packages id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 3.2 项目名称+项目编码+项目时间 if projectCode != "" && projectDate != "" { newName := projectName + "_" + projectCode + "_" + projectDate id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 3.3 项目名称+项目编码+采购单位 if projectCode != "" && buyer != "" { newName := projectName + "_" + projectCode + "_" + buyer id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 3.4 项目名称+分包+项目时间 if packages != "" && projectDate != "" { newName := projectName + "_" + packages + "_" + projectDate id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 3.5 项目名称+分包+采购单位 if packages != "" && buyer != "" { newName := projectName + "_" + packages + "_" + buyer id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 3.6 项目名称+项目时间+采购单位 if projectDate != "" && buyer != "" { newName := projectName + "_" + projectDate + "_" + buyer id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 4.1 项目名称+项目编码+分包信息+项目时间 if projectCode != "" && packages != "" && projectDate != "" { newName := projectName + "_" + projectCode + "_" + packages + "_" + projectDate id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 4.2 项目名称+项目编码+分包信息+采购单位 if projectCode != "" && packages != "" && buyer != "" { newName := projectName + "_" + projectCode + "_" + packages + "_" + buyer id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } //TODO 5 项目名称+项目编码+分包信息+项目时间+采购单位 if projectCode != "" && packages != "" && projectDate != "" && buyer != "" { newName := projectName + "_" + projectCode + "_" + packages + "_" + projectDate + "_" + buyer id = hash(newName) if !cache.Contains(uint32(id)) { return newName } } now := time.Now().Format("2006-01-02") newName := projectName + "_" + projectCode + "_" + packages + "_" + projectDate + "_" + buyer + "_" + now id = hash(newName) if !cache.Contains(uint32(id)) { return newName } return "" } // getRename 获取新的不重复名称 func getRename(c *gin.Context) { var data = ProjectData{} err := c.ShouldBindJSON(&data) if err != nil { log.Println("ShouldBindJSON", err) c.JSON(200, map[string]interface{}{ "code": 0, "msg": "参数识别错误,请检查参数", "data": nil, }) return } newName := RenameProjectName(data.ProjectName, data.ProjectCode, data.Packages, data.ProjectDate, data.Buyer) if newName != "" { c.JSON(200, map[string]interface{}{ "code": 0, "msg": "请求成功", "data": newName, }) } else { c.JSON(200, map[string]interface{}{ "code": -1, "msg": "提供参数,无法获取到唯一不重复项目名称", "data": newName, }) } }