commit 5e9e1418a2d974275e7608b8838c26ff8421afd4 Author: hoteas Date: Fri Aug 4 08:20:59 2017 +0000 diff --git a/.idea/hotime.iml b/.idea/hotime.iml new file mode 100644 index 0000000..c2f07d0 --- /dev/null +++ b/.idea/hotime.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/GOPATH__hotime_.xml b/.idea/libraries/GOPATH__hotime_.xml new file mode 100644 index 0000000..790b4ff --- /dev/null +++ b/.idea/libraries/GOPATH__hotime_.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..ce2eb0a --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,31 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e6dff29 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/preferred-vcs.xml b/.idea/preferred-vcs.xml new file mode 100644 index 0000000..848cfc4 --- /dev/null +++ b/.idea/preferred-vcs.xml @@ -0,0 +1,6 @@ + + + + ApexVCS + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..78e665f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..d6d4909 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,912 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + limit + Ping + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + project + + + + + + + + + + + + + + + + project + + + true + + + + DIRECTORY + + false + + + + + + + C:\Users\彭\AppData\Roaming\Subversion + 125 + + + + + + + + + 1500277689857 + + + 1500458878821 + + + 1500963445543 + + + 1501144370472 + + + 1501471458592 + + + 1501483845216 + + + 1501582471326 + + + 1501670291054 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app.go b/app.go new file mode 100644 index 0000000..4a51ef9 --- /dev/null +++ b/app.go @@ -0,0 +1,247 @@ +package hotime + +import ( + "bytes" + "database/sql" + "encoding/json" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "strconv" + "strings" +) + +type App struct { + Router + Error + Port int //端口号 + connectListener func(context Context) bool //所有的访问监听,true按原计划继续使用,false表示有监听器处理 + connectDbFunc func(err ...*Error) *sql.DB + configPath string + Config Map + Db HoTimeDB + CacheIns + sessionLong CacheIns + sessionShort CacheIns +} + +//启动实例 +func (this *App) Run(router Router, port int) { + this.Router = router + this.Port = port + + if this.connectDbFunc != nil { + this.Db.SetConnect(this.connectDbFunc) + } + + if this.CacheIns == nil { + this.CacheIns = CacheIns(&CacheMemory{Map: Map{}, Time: this.Config.GetInt64("cacheShortTime")}) + } + + http.HandleFunc("/", this.handler) + + http.ListenAndServe(":"+ObjToStr(port), nil) +} + +//启动实例 +func (this *App) SetConnectDB(connect func(err ...*Error) *sql.DB) { + this.connectDbFunc = connect +} + +//设置配置文件路径全路径或者相对路径 +func (this *App) SetSession(short CacheIns, Long CacheIns) { + this.sessionLong = Long + this.sessionShort = short + +} + +//默认配置缓存和session实现 +func (this *App) SetDefault(connect func(err ...*Error) *sql.DB) { + this.SetConfig() + this.connectDbFunc = connect + //防止手动设置缓存误伤 + if this.CacheIns == nil { + this.SetCache(CacheIns(&CacheMemory{})) + } + //防止手动设置session误伤 + if this.sessionShort == nil && this.sessionLong == nil { + if this.connectDbFunc == nil { + this.SetSession(CacheIns(&CacheMemory{}), nil) + } else { + this.SetSession(CacheIns(&CacheMemory{}), CacheIns(&CacheDb{Db: &this.Db, Time: this.Config.GetInt64("cacheLongTime")})) + } + + } + +} + +//设置配置文件路径全路径或者相对路径 +func (this *App) SetCache(cache CacheIns) { + + this.CacheIns = cache + +} + +//设置配置文件路径全路径或者相对路径 +func (this *App) SetConfig(configPath ...string) { + if len(configPath) != 0 { + this.configPath = configPath[0] + } + + if this.configPath == "" { + this.configPath = "config/config.json" + } + //加载配置文件 + btes, err := ioutil.ReadFile(this.configPath) + this.Config = DeepCopyMap(Config).(Map) + if err == nil { + + cmap := Map{} + //文件是否损坏 + cmap.JsonToMap(string(btes), &this.Error) + + for k, v := range cmap { + this.Config.Put(k, v) + } + } + //文件如果损坏则不写入配置防止配置文件数据丢失 + if this.Error.GetError() == nil { + var out bytes.Buffer + + err = json.Indent(&out, []byte(this.Config.ToJsonString()), "", "\t") + + err = ioutil.WriteFile(this.configPath, out.Bytes(), os.ModeAppend) + if err != nil { + os.MkdirAll(filepath.Dir(this.configPath), os.ModeDir) + os.Create(this.configPath) + err = ioutil.WriteFile(this.configPath, out.Bytes(), os.ModeAppend) + + if err != nil { + this.Error.SetError(err) + } + } + + } else { + this.Error.SetError(nil) + } + +} + +//连接判断,返回true继续传输至控制层,false则停止传输 +func (this *App) SetConnectListener(lis func(context Context) bool) { + this.connectListener = lis +} + +//网络错误 +func (this *App) session(w http.ResponseWriter, req *http.Request) { + +} + +//访问 +func (this *App) handler(w http.ResponseWriter, req *http.Request) { + + q := strings.Index(req.RequestURI, "?") + if q == -1 { + q = len(req.RequestURI) + } + o := Substr(req.RequestURI, 0, q) + + r := strings.SplitN(o, "/", -1) + + var s = make([]string, 0) + + for i := 0; i < len(r); i++ { + if !strings.EqualFold("", r[i]) { + s = append(s, r[i]) + } + } + + //接口服务 + if len(s) == 3 { + //如果满足规则则路由到对应控制器去 + if this.Router[s[0]] != nil && this.Router[s[0]][s[1]] != nil && this.Router[s[0]][s[1]][s[2]] != nil { + + //获取cookie + // 如果cookie存在直接将sessionId赋值为cookie.Value + // 如果cookie不存在就查找传入的参数中是否有token + // 如果token不存在就生成随机的sessionId + // 如果token存在就判断token是否在Session中有保存 + // 如果有取出token并复制给cookie + // 没有保存就生成随机的session + cookie, err := req.Cookie((Config["sessionName"]).(string)) + sessionId := Md5(strconv.Itoa(Rand(10))) + token := req.FormValue("token") + //isFirst:=false + if err != nil || (len(token) == 32 && cookie.Value != token) { + if len(token) == 32 { + sessionId = token + } + //else{ + // isFirst=true; + //} + http.SetCookie(w, &http.Cookie{Name: Config["sessionName"].(string), Value: sessionId, Path: "/"}) + } else { + sessionId = cookie.Value + } + + //访问实例 + context := Context{SessionIns: SessionIns{SessionId: sessionId, + LongCache: this.sessionLong, + ShortCache: this.sessionShort, + }, + CacheIns: this.CacheIns, + Resp: w, Req: req, App: this, RouterString: s, Config: this.Config, Db: &this.Db} + + //访问拦截 + if this.connectListener != nil { + if !this.connectListener(context) { + return + } + } + //控制层 + this.Router[s[0]][s[1]][s[2]](&context) + context.View() + return + } + + } + + //url赋值 + path := Config.GetString("tpt") + o + + //判断是否为默认 + if path[len(path)-1] == '/' { + defFile := Config["defFile"].([]string) + for i := 0; i < len(defFile); i++ { + temp := path + defFile[i] + _, err := os.Stat(temp) + + if err == nil { + path = temp + break + } + } + if path[len(path)-1] == '/' { + w.WriteHeader(404) + return + } + } + + if strings.Contains(path, "/.") { + w.WriteHeader(404) + return + } + + header := w.Header() + + //类型判断并设置Content-Type + if strings.Contains(path, ".css") { + header.Set("Content-Type", "text/css") + //header.Get(Config["sessionName"].(string)) + } + header.Set("Cache-Control", "public") + //w.Write(data) + http.ServeFile(w, req, path) + +} diff --git a/cachedb.go b/cachedb.go new file mode 100644 index 0000000..45a5e9e --- /dev/null +++ b/cachedb.go @@ -0,0 +1,107 @@ +package hotime + +import ( + "encoding/json" + "time" +) + +type CacheDb struct { + Time int64 + Db *HoTimeDB + Error + isInit bool +} + +func (this *CacheDb) initDbTable() { + if this.isInit { + return + } + + dbNames := this.Db.Query("SELECT DATABASE()") + + if len(dbNames) == 0 { + return + } + dbName := dbNames[0].GetString("DATABASE()") + res := this.Db.Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='" + dbName + "' AND TABLE_NAME='cached'") + if len(res) == 0 { + this.Db.Exec("CREATE TABLE `cached` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `ckey` varchar(60) DEFAULT NULL, `cvalue` varchar(2000) DEFAULT NULL, `time` bigint(20) DEFAULT NULL, `endtime` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=198740 DEFAULT CHARSET=utf8") + } + this.isInit = true + +} + +//获取Cache键只能为string类型 +func (this *CacheDb) get(key string) interface{} { + + cached := this.Db.Get("cached", "*", Map{"ckey": key}) + + if cached == nil { + return nil + } + //data:=cacheMap[key]; + if cached.GetInt64("endtime") <= time.Now().Unix() { + + this.Db.Delete("cached", Map{"id": cached.GetString("id")}) + return nil + } + + data := Map{} + data.JsonToMap(cached.GetString("cvalue")) + + return data.Get("data") +} + +//key value ,时间为时间戳 +func (this *CacheDb) set(key string, value interface{}, tim int64) { + + bte, _ := json.Marshal(Map{"data": value}) + + num := this.Db.Update("cached", Map{"cvalue": string(bte), "time": time.Now().UnixNano(), "endtime": tim}, Map{"ckey": key}) + if num == int64(0) { + this.Db.Insert("cached", Map{"cvalue": string(bte), "time": time.Now().UnixNano(), "endtime": tim, "ckey": key}) + } + + //随机执行删除命令 + if Rand(1000) > 950 { + this.Db.Delete("cached", Map{"endtime[<]": time.Now().Unix()}) + } +} + +func (this *CacheDb) delete(key string) { + this.Db.Delete("cached", Map{"ckey": key}) +} + +func (this *CacheDb) Cache(key string, data ...interface{}) *Obj { + + this.initDbTable() + + if len(data) == 0 { + return &Obj{Data: this.get(key)} + } + tim := time.Now().Unix() + + if len(data) == 1 && data[0] == nil { + this.delete(key) + return &Obj{Data: nil} + } + + if len(data) == 1 { + if this.Time == 0 { + this.Time = Config.GetInt64("cacheLongTime") + } + tim += this.Time + } + if len(data) == 2 { + this.SetError(nil) + tempt := ObjToInt64(data[1], &this.Error) + + if this.GetError() == nil { + + tim = tim + tempt + + } + } + this.set(key, data[0], tim) + return &Obj{Data: nil} +} diff --git a/cachememory.go b/cachememory.go new file mode 100644 index 0000000..9333da7 --- /dev/null +++ b/cachememory.go @@ -0,0 +1,93 @@ +package hotime + +import ( + "time" +) + +type CacheMemory struct { + Time int64 + Map + Error +} + +//获取Cache键只能为string类型 +func (this *CacheMemory) get(key string) interface{} { + this.Error.SetError(nil) + if this.Map[key]==nil{ + return nil + } + data := this.Map.Get(key, &this.Error).(cacheData) + if this.GetError() != nil { + return nil + } + //data:=cacheMap[key]; + if data.time <= time.Now().Unix() { + delete(this.Map, key) + return nil + } + return data.data +} + +//key value ,时间为时间戳 +func (this *CacheMemory) set(key string, value interface{}, time int64) { + this.Error.SetError(nil) + var data cacheData + dd := this.Map.Get(key, &this.Error) + + if dd == nil { + data = cacheData{} + } else { + data = dd.(cacheData) + } + + data.time = time + data.data = value + + if this.Map==nil{ + this.Map=Map{} + } + this.Map.Put(key,data) +} + +func (this *CacheMemory) delete(key string) { + + delete(this.Map, key) +} + +func (this *CacheMemory) Cache(key string, data ...interface{}) *Obj { + + return SafeMutex(MUTEX_MEMORY_CACHE, func() interface{} { + + if len(data) == 0 { + return &Obj{Data: this.get(key)} + } + tim := time.Now().Unix() + + if len(data) == 1 && data[0] == nil { + this.delete(key) + return &Obj{Data: nil} + } + + if len(data) == 1 { + + if this.Time == 0 { + this.Time = Config.GetInt64("cacheShortTime") + } + + tim += this.Time + } + if len(data) == 2 { + this.Error.SetError(nil) + tempt := ObjToInt64(data[1], &this.Error) + if this.GetError() == nil { + + tim = tim + tempt + + } + } + + this.set(key, data[0], tim) + return &Obj{Data: nil} + }).(*Obj) + +} diff --git a/const.go b/const.go new file mode 100644 index 0000000..4d88c38 --- /dev/null +++ b/const.go @@ -0,0 +1,18 @@ +package hotime + +const ( + LOG_FMT = 0 + LOG_NIL = 1 +) + +//锁关键字 +const ( + MUTEX_MAP = "HOTIME-MAP" + MUTEX_SLICE = "HOTIME-SLICE" + MUTEX_MEMORY_CACHE = "HOTIME-MUTEX-MEMORYCACHE" +) + +//锁关键字 +const ( + SESSION_TYPE = "SESSION-TYPE#" +) \ No newline at end of file diff --git a/context.go b/context.go new file mode 100644 index 0000000..6dc0523 --- /dev/null +++ b/context.go @@ -0,0 +1,68 @@ +package hotime + +import ( + "encoding/json" + "net/http" + "time" +) + +type Context struct { + LastErr Error + tag int64 + Resp http.ResponseWriter + Req *http.Request + App *App + RouterString []string + Config Map + Db *HoTimeDB + resp Map + CacheIns + SessionIns +} + +//唯一标志 +func (this *Context) GetTag() int64 { + + if this.tag == int64(0) { + this.tag = time.Now().UnixNano() + } + return this.tag +} + +//唯一标志 +func (this *Context) Mtd(router [3]string) Map { + this.App.Router[router[0]][router[1]][router[2]](this) + d := this.resp + this.resp = nil + return d +} + +//打印 +func (this *Context) Display(statu int, data interface{}) { + + resp := Map{"statu": statu} + if statu != 0 { + temp := Map{} + temp["type"] = 0 + temp["msg"] = data + resp["result"] = temp + } else { + resp["result"] = data + } + + this.resp = resp + + //this.Data=d; +} + +func (this *Context) View() { + if this.resp == nil { + return + } + d, err := json.Marshal(this.resp) + if err != nil { + return + } + this.resp = nil + this.Resp.Write(d) +} diff --git a/db.go b/db.go new file mode 100644 index 0000000..d005258 --- /dev/null +++ b/db.go @@ -0,0 +1,807 @@ +package hotime + +import ( + "database/sql" + "encoding/json" + "errors" + "os" + "reflect" + "strings" +) + +type HoTimeDB struct { + *sql.DB + Context + Cached bool + LastQuery string + LastData []interface{} + ConnectFunc func(err ...*Error) *sql.DB + //LastErr Error + limit Slice +} + +//设置数据库配置连接 +func (this *HoTimeDB) SetConnect(connect func(err ...*Error) *sql.DB, err ...*Error) { + this.ConnectFunc = connect + this.InitDb() +} + +func (this *HoTimeDB) InitDb(err ...*Error) Error { + if len(err) != 0 { + this.LastErr = *(err[0]) + } + this.DB = this.ConnectFunc(&this.LastErr) + if this.DB == nil { + + return this.LastErr + } + e := this.DB.Ping() + + this.LastErr.SetError(e) + + return this.LastErr +} + +func (this *HoTimeDB) Page(page, pageRow int) *HoTimeDB { + page = (page - 1) * pageRow + if page < 0 { + page = 1 + } + + this.limit = Slice{page, pageRow} + return this +} + +func (this *HoTimeDB) PageSelect(table string, qu ...interface{}) []Map { + + if len(qu) == 1 { + qu = append(qu, Map{"LIMIT": this.limit}) + } + if len(qu) == 2 { + temp := qu[1].(Map) + temp["LIMIT"] = this.limit + qu[1] = temp + } + if len(qu) == 3 { + temp := qu[2].(Map) + temp["LIMIT"] = this.limit + qu[2] = temp + } + //fmt.Println(qu) + data := this.Select(table, qu...) + + return data +} + +//数据库数据解析 +func (this *HoTimeDB) Row(resl *sql.Rows) []Map { + dest := make([]Map, 0) + strs, _ := resl.Columns() + + for i := 0; resl.Next(); i++ { + lis := make(Map, 0) + a := make([]interface{}, len(strs)) + + b := make([]interface{}, len(a)) + for j := 0; j < len(a); j++ { + b[j] = &a[j] + } + resl.Scan(b...) + for j := 0; j < len(a); j++ { + if a[j] != nil && reflect.ValueOf(a[j]).Type().String() == "[]uint8" { + lis[strs[j]] = string(a[j].([]byte)) + } else { + lis[strs[j]] = a[j] + } + + } + + dest = append(dest, lis) + + } + + return dest +} + +// +////code=0,1,2 0 backup all,1 backup data,2 backup ddl +//func (this *HoTimeDB) Backup(path string, code int) { +// var cmd *exec.Cmd +// switch code { +// case 0:cmd= exec.Command("mysqldump","-h"+ObjToStr(Config["dbHost"]), "-P"+ObjToStr(Config["dbPort"]),"-u"+ObjToStr(Config["dbUser"]), "-p"+ObjToStr(Config["dbPwd"]),ObjToStr(Config["dbName"])) +// case 1:cmd= exec.Command("mysqldump","-h"+ObjToStr(Config["dbHost"]), "-P"+ObjToStr(Config["dbPort"]),"-u"+ObjToStr(Config["dbUser"]), "-p"+ObjToStr(Config["dbPwd"]), ObjToStr(Config["dbName"])) +// case 2:cmd= exec.Command("mysqldump","--no-data","-h"+ObjToStr(Config["dbHost"]), "-P"+ObjToStr(Config["dbPort"]),"-u"+ObjToStr(Config["dbUser"]), "-p"+ObjToStr(Config["dbPwd"]),ObjToStr(Config["dbName"])) +// } +// +// +// +// stdout, err := cmd.StdoutPipe() +// if err != nil { +// log.Fatal(err) +// } +// +// if err := cmd.Start(); err != nil { +// log.Fatal(err) +// } +// +// bytes, err := ioutil.ReadAll(stdout) +// if err != nil { +// log.Fatal(err) +// } +// err = ioutil.WriteFile(path, bytes, 0644) +// if err != nil { +// panic(err) +// } +// return ; +// // +// //db := `` +// //fmt.Println(db) +// // +// //tables := this.Query("show tables") +// //lth := len(tables) +// //if lth == 0 { +// // return +// //} +// //for k, _ := range tables[0] { +// // db = Substr(k, 10, len(k)) +// //} +// // +// //fd, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) +// //fd.Write([]byte("/*datetime " + time.Now().Format("2006-01-02 15:04:05") + " */ \r\n")) +// //fd.Close() +// // +// //for i := 0; i < lth; i++ { +// // tt := tables[i]["Tables_in_"+db].(string) +// // this.backupSave(path, tt, code) +// // debug.FreeOSMemory() +// //} +// +//} + +func (this *HoTimeDB) backupSave(path string, tt string, code int) { + fd, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) + defer fd.Close() + + str := "\r\n" + if code == 0 || code == 2 { + str += this.backupDdl(tt) + } + + if code == 0 || code == 1 { + str += "insert into `" + tt + "`\r\n\r\n(" + str += this.backupCol(tt) + } + + fd.Write([]byte(str)) +} +func (this *HoTimeDB) backupDdl(tt string) string { + + data := this.Query("show create table " + tt) + if len(data) == 0 { + return "" + } + + return ObjToStr(data[0]["Create Table"]) + ";\r\n\r\n" +} + +func (this *HoTimeDB) backupCol(tt string) string { + str := "" + data := this.Select(tt, "*") + + lthData := len(data) + + if lthData == 0 { + return str + } + lthCol := len(data[0]) + col := make([]string, lthCol) + tempLthData := 0 + for k, _ := range data[0] { + + if tempLthData == lthCol-1 { + str += "`" + k + "`)" + } else { + str += "`" + k + "`," + } + col[tempLthData] = k + tempLthData++ + } + + str += " values" + + for j := 0; j < lthData; j++ { + + for m := 0; m < lthCol; m++ { + + if m == 0 { + str += "(" + } + + v := "NULL" + if data[j][col[m]] != nil { + v = "'" + strings.Replace(ObjToStr(data[j][col[m]]), "'", `\'`, -1) + "'" + } + + if m == lthCol-1 { + str += v + ")" + + } else { + str += v + "," + } + } + if j == lthData-1 { + str += ";\r\n\r\n" + } else { + str += ",\r\n\r\n" + } + } + return str +} + +func (this *HoTimeDB) md5(query string, args ...interface{}) string { + strByte, _ := json.Marshal(args) + str := Md5(query + ":" + string(strByte)) + return str +} + +func (this *HoTimeDB) Query(query string, args ...interface{}) []Map { + + //fmt.Println(query) + var err error + var resl *sql.Rows + + this.LastQuery = query + this.LastData = args + + if this.DB == nil { + err = errors.New("没有初始化数据库") + this.LastErr.SetError(err) + return nil + } + resl, err = this.DB.Query(query, args...) + this.LastErr.SetError(err) + if err != nil { + if err = this.DB.Ping(); err != nil { + this.LastErr.SetError(err) + this.InitDb() + if this.LastErr.GetError() != nil { + return nil + } + return this.Query(query, args...) + } + return nil + } + + return this.Row(resl) +} + +func (this *HoTimeDB) Exec(query string, args ...interface{}) (sql.Result, Error) { + + this.LastQuery = query + this.LastData = args + if this.DB == nil { + err := errors.New("没有初始化数据库") + this.LastErr.SetError(err) + return nil, this.LastErr + } + + resl, e := this.DB.Exec(query, args...) + + this.LastErr.SetError(e) + + //判断是否连接断开了 + if e != nil { + + if e = this.DB.Ping(); e != nil { + this.LastErr.SetError(e) + this.InitDb() + if this.LastErr.GetError() != nil { + return resl, this.LastErr + } + return this.Exec(query, args...) + } + } + + return resl, this.LastErr +} + +//func (this *HoTimeDB)copy(data []Map)[]Map{ +// if data==nil{ +// return nil +// } +// +// lth:=len(data) +// +// res:=make([]Map,lth) +// +// +// for i:=0;i 0 { + if reflect.ValueOf(qu[intQs]).Type().String() == "string" { + query += " " + qu[intQs].(string) + } else { + for i := 0; i < len(qu[intQs].(Slice)); i++ { + if i+1 != len(qu[intQs].(Slice)) { + query += " `" + qu[intQs].(Slice)[i].(string) + "`," + } else { + query += " `" + qu[intQs].(Slice)[i].(string) + "`" + } + + } + } + + } else { + query += " *" + } + + query += " FROM " + table + + if join { + for k, v := range qu[0].(Map) { + switch Substr(k, 0, 3) { + case "[>]": + query += " LEFT JOIN " + Substr(k, 3, len(k)-3) + " ON " + v.(string) + case "[<]": + query += " RIGHT JOIN " + Substr(k, 3, len(k)-3) + " ON " + v.(string) + } + switch Substr(k, 0, 4) { + case "[<>]": + query += " FULL JOIN " + Substr(k, 4, len(k)-4) + " ON " + v.(string) + case "[><]": + query += " INNER JOIN " + Substr(k, 4, len(k)-4) + " ON " + v.(string) + } + } + } + + if len(qu) > 1 { + where = qu[intWhere].(Map) + } + + temp, resWhere := this.where(where) + + query += temp + qs = append(qs, resWhere...) + + res := this.Query(query, qs...) + + return res + +} + +func (this *HoTimeDB) Get(table string, qu ...interface{}) Map { + //fmt.Println(qu) + if len(qu) == 1 { + qu = append(qu, Map{"LIMIT": 1}) + } + if len(qu) == 2 { + temp := qu[1].(Map) + temp["LIMIT"] = 1 + qu[1] = temp + } + if len(qu) == 3 { + temp := qu[2].(Map) + temp["LIMIT"] = 1 + qu[2] = temp + } + //fmt.Println(qu) + data := this.Select(table, qu...) + if len(data) == 0 { + return nil + } + return data[0] +} + +/** +** 计数 + */ +func (this *HoTimeDB) Count(table string, qu ...interface{}) int { + req := []interface{}{} + + if len(qu) == 2 { + req = append(req, qu[0]) + req = append(req, "COUNT(*)") + req = append(req, qu[1]) + } else { + req = append(req, "COUNT(*)") + req = append(req, qu...) + } + + //req=append(req,qu...) + data := this.Select(table, req...) + //fmt.Println(data) + if len(data) == 0 { + return 0 + } + //res,_:=StrToInt(data[0]["COUNT(*)"].(string)) + res := ObjToStr(data[0]["COUNT(*)"]) + count, _ := StrToInt(res) + return count + +} + +var condition = []string{"AND", "OR"} +var vcond = []string{"GROUP", "ORDER", "LIMIT"} + +//where语句解析 +func (this *HoTimeDB) where(data Map) (string, []interface{}) { + + where := "" + + res := make([]interface{}, 0) + //AND OR判断 + for k, v := range data { + x := 0 + for i := 0; i < len(condition); i++ { + + if condition[i] == k { + + tw, ts := this.cond(k, v.(Map)) + + where += tw + res = append(res, ts...) + break + } + x++ + } + + y := 0 + for j := 0; j < len(vcond); j++ { + + if vcond[j] == k { + break + } + y++ + } + if x == len(condition) && y == len(vcond) { + tv, vv := this.varCond(k, v) + + where += tv + res = append(res, vv...) + } + + } + + if len(where) != 0 { + where = " WHERE " + where + } + + //特殊字符 + for j := 0; j < len(vcond); j++ { + for k, v := range data { + if vcond[j] == k { + if k == "ORDER" { + where += " " + k + " BY " + //fmt.Println(reflect.ValueOf(v).Type()) + + //break + } else if k == "GROUP" { + + where += " " + k + " BY " + } else { + + where += " " + k + } + + if reflect.ValueOf(v).Type().String() == "hotime.Slice" { + for i := 0; i < len(v.(Slice)); i++ { + where += " " + ObjToStr(v.(Slice)[i]) + + if len(v.(Slice)) != i+1 { + where += "," + } + + } + } else { + //fmt.Println(v) + where += " " + ObjToStr(v) + } + + break + } + } + + } + + return where, res + +} + +func (this *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) { + where := "" + res := make([]interface{}, 0) + length := len(k) + if length > 4 { + def := false + switch Substr(k, length-3, 3) { + case "[>]": + k = strings.Replace(k, "[>]", "", -1) + where += "`" + k + "`>? " + res = append(res, v) + case "[<]": + k = strings.Replace(k, "[<]", "", -1) + where += "`" + k + "`=]": + k = strings.Replace(k, "[>=]", "", -1) + where += "`" + k + "`>=? " + res = append(res, v) + case "[<=]": + k = strings.Replace(k, "[<]", "", -1) + where += "`" + k + "`<=? " + res = append(res, v) + case "[><]": + k = strings.Replace(k, "[><]", "", -1) + where += "`" + k + "` NOT BETWEEN ? AND ? " + res = append(res, v.(Slice)[0]) + res = append(res, v.(Slice)[1]) + case "[<>]": + k = strings.Replace(k, "[<>]", "", -1) + where += "`" + k + "` BETWEEN ? AND ? " + res = append(res, v.(Slice)[0]) + res = append(res, v.(Slice)[1]) + default: + if reflect.ValueOf(v).Type().String() == "hotime.Slice" { + where += "`" + k + "` IN (" + res = append(res, (v.(Slice))...) + for i := 0; i < len(v.(Slice)); i++ { + if i+1 != len(v.(Slice)) { + where += "?," + } else { + where += "?) " + } + //res=append(res,(v.(Slice))[i]) + } + } else { + where += "`" + k + "`=? " + res = append(res, v) + } + + } + } + + } else { + //fmt.Println(reflect.ValueOf(v).Type().String()) + if reflect.ValueOf(v).Type().String() == "hotime.Slice" { + + //fmt.Println(v) + where += "`" + k + "` IN (" + res = append(res, (v.(Slice))...) + for i := 0; i < len(v.(Slice)); i++ { + if i+1 != len(v.(Slice)) { + where += "?," + } else { + where += "?) " + } + //res=append(res,(v.(Slice))[i]) + } + } else if reflect.ValueOf(v).Type().String() == "[]interface {}" { + where += "`" + k + "` IN (" + res = append(res, (v.([]interface{}))...) + for i := 0; i < len(v.([]interface{})); i++ { + if i+1 != len(v.([]interface{})) { + where += "?," + } else { + where += "?) " + } + //res=append(res,(v.(Slice))[i]) + } + } else { + where += "`" + k + "`=? " + res = append(res, v) + } + } + + return where, res +} + +// this.Db.Update("user",hotime.Map{"ustate":"1"},hotime.Map{"AND":hotime.Map{"OR":hotime.Map{"uid":4,"uname":"dasda"}},"ustate":1}) +func (this *HoTimeDB) notIn(k string, v interface{}, where string, res []interface{}) (string, []interface{}) { + //where:="" + //fmt.Println(reflect.ValueOf(v).Type().String()) + if reflect.ValueOf(v).Type().String() == "hotime.Slice" { + where += "`" + k + "` NOT IN (" + res = append(res, (v.(Slice))...) + for i := 0; i < len(v.(Slice)); i++ { + if i+1 != len(v.(Slice)) { + where += "?," + } else { + where += "?) " + } + //res=append(res,(v.(Slice))[i]) + } + } else if reflect.ValueOf(v).Type().String() == "[]interface {}" { + where += "`" + k + "` NOT IN (" + res = append(res, (v.([]interface{}))...) + for i := 0; i < len(v.([]interface{})); i++ { + if i+1 != len(v.([]interface{})) { + where += "?," + } else { + where += "?) " + } + //res=append(res,(v.(Slice))[i]) + } + } else { + where += "`" + k + "` !=? " + res = append(res, v) + } + + return where, res +} + +func (this *HoTimeDB) cond(tag string, data Map) (string, []interface{}) { + where := " " + res := make([]interface{}, 0) + lens := len(data) + //fmt.Println(lens) + for k, v := range data { + x := 0 + for i := 0; i < len(condition); i++ { + + if condition[i] == k { + + tw, ts := this.cond(k, v.(Map)) + if lens--; lens <= 0 { + //fmt.Println(lens) + where += "(" + tw + ") " + } else { + where += "(" + tw + ") " + tag + " " + } + + res = append(res, ts...) + break + } + x++ + } + + if x == len(condition) { + + tv, vv := this.varCond(k, v) + + res = append(res, vv...) + if lens--; lens <= 0 { + where += tv + "" + } else { + where += tv + " " + tag + " " + } + } + + } + + return where, res +} + +//更新数据 +func (this *HoTimeDB) Update(table string, data Map, where Map) int64 { + + query := "UPDATE " + table + " SET " + //UPDATE Person SET Address = 'Zhongshan 23', City = 'Nanjing' WHERE LastName = 'Wilson' + qs := make([]interface{}, 0) + tp := len(data) + + for k, v := range data { + vstr := "?" + if Substr(k, len(k)-3, 3) == "[#]" { + k = strings.Replace(k, "[#]", "", -1) + + vstr = ObjToStr(v) + } else { + qs = append(qs, v) + } + query += "`" + k + "`=" + vstr + "" + if tp--; tp != 0 { + query += ", " + } + } + + temp, resWhere := this.where(where) + //fmt.Println(resWhere) + + query += temp + qs = append(qs, resWhere...) + + res, err := this.Exec(query, qs...) + + if err.GetError() != nil { + + return 0 + } + + //return 0 + rows, _ := res.RowsAffected() + return rows +} + +func (this *HoTimeDB) Delete(table string, data map[string]interface{}) int64 { + + query := "DELETE FROM " + table + " " + + temp, resWhere := this.where(data) + query += temp + + res, err := this.Exec(query, resWhere...) + + if err.GetError() != nil { + return 0 + } + + //return 0 + rows, _ := res.RowsAffected() + return rows +} + +//插入新数据 +func (this *HoTimeDB) Insert(table string, data map[string]interface{}) int64 { + + values := make([]interface{}, 0) + queryString := " (" + valueString := " (" + + lens := len(data) + tempLen := 0 + for k, v := range data { + tempLen++ + values = append(values, v) + if tempLen < lens { + queryString += "`" + k + "`," + valueString += "?," + } else { + queryString += "`" + k + "`) " + valueString += "?);" + } + + } + query := "INSERT INTO " + table + queryString + "VALUES" + valueString + + res, err := this.Exec(query, values...) + + if err.GetError() != nil { + + return 0 + } + + id, e := res.LastInsertId() + this.LastErr.SetError(e) + if e != nil { + return 0 + } + //fmt.Println(id) + return id +} diff --git a/error.go b/error.go new file mode 100644 index 0000000..59e39ac --- /dev/null +++ b/error.go @@ -0,0 +1,38 @@ +package hotime + +import "fmt" + +//框架层处理错误 +type Error struct { + err error +} + +func(this *Error)GetError()error{ + + return this.err + +} + +func(this *Error)SetError(err error,loglevel... int){ + + SafeMutex("HOTIME-SYSTEM-ERR", func() interface{} { + if err==nil{ + this.err=err + return nil + } + + lev:=Config.GetInt("logLevel") + + if len(loglevel)!=0{ + lev=loglevel[0] + } + + if lev==LOG_FMT{ + fmt.Println(err) + } + this.err=err + return nil + }) + + +} diff --git a/func.go b/func.go new file mode 100644 index 0000000..3788609 --- /dev/null +++ b/func.go @@ -0,0 +1,303 @@ +package hotime + +import ( + //"reflect" + "crypto/md5" + "encoding/hex" + "math" + "math/rand" + "strings" + //"fmt" + "sync" + "time" +) + +//安全锁 +func SafeMutex(tag string, f func() interface{}) interface{} { + + mutexer.Lock() + if mutex[tag] == nil { + + mutex[tag] = &sync.RWMutex{} + + } + mutexer.Unlock() + + mutex[tag].Lock() + res := f() + mutex[tag].Unlock() + return res +} + +//字符串首字符大写 +func StrFirstToUpper(str string) string { + if len(str) == 0 { + return str + } + + first := Substr(str, 0, 1) + other := Substr(str, 1, len(str)-1) + + return strings.ToUpper(first) + other +} + +//字符串截取 +func Substr(str string, start int, length int) string { + rs := []rune(str) + rl := len(rs) + end := 0 + + if start < 0 { + start = rl - 1 + start + } + end = start + length + + if start > end { + start, end = end, start + } + + if start < 0 { + start = 0 + } + if start > rl { + start = rl + } + if end < 0 { + end = 0 + } + if end > rl { + end = rl + } + + return string(rs[start:end]) +} + +//获取最后出现字符串的下标 +//return 找不到返回 -1 +func IndexLastStr(str, sep string) int { + sepSlice := []rune(sep) + strSlice := []rune(str) + if len(sepSlice) > len(strSlice) { + return -1 + } + + v := sepSlice[len(sepSlice)-1] + + for i := len(strSlice) - 1; i >= 0; i-- { + vs := strSlice[i] + if v == vs { + j := len(sepSlice) - 2 + for ; j >= 0; j-- { + vj := sepSlice[j] + vsj := strSlice[i-(len(sepSlice)-j-1)] + if vj != vsj { + break + } + } + if j < 0 { + return i - len(sepSlice) + 1 + } + } + + } + return -1 +} + +//md5 +func Md5(req string) string { + md5Ctx := md5.New() + md5Ctx.Write([]byte(req)) + cipherStr := md5Ctx.Sum(nil) + return hex.EncodeToString(cipherStr) +} + +//随机数 +func Rand(count int) int { + //随机对象 + var R = rand.New(rand.NewSource(time.Now().UnixNano())) + res := 0 + for i := 0; i < count; i++ { + res = res * 10 + res = res + R.Intn(10) + if i == 0 && res == 0 { + for { + res = res + R.Intn(10) + if res != 0 { + break + } + } + } + } + return res +} + +//随机数范围 +func RandX(small int, max int) int { + res := 0 + //随机对象 + var R = rand.New(rand.NewSource(time.Now().UnixNano())) + if small == max { + return small + } + + for { + res = R.Intn(max) + if res >= small { + break + } + } + return res +} + +// +////路由 +//func Router(ctr CtrInterface) { +// +// str := reflect.ValueOf(ctr).Type().String() +// a := strings.IndexByte(str, '.') +// +// c := len(str) - len("Ctr") - 1 +// +// app := Substr(str, 0, a) //属于哪个app +// ct := Substr(str, a+1, c-a) //属于哪个控制器 +// var x = map[string]CtrInterface{} +// if _, ok := Proj[app]; ok { +// //存在APP +// x = Proj[app] +// } else { +// x = map[string]CtrInterface{} +// } +// x[ct] = ctr //将控制器存入APP +// // fmt.Println(c) +// Proj[app] = x //将APP存入测试 +//} +// +//func RunMethodListener(test func(app []string)) { +// RunMethodListenerFunc = test +//} + +//func SetDb(db *sql.DB) { +// db.SetMaxOpenConns(2000) +// db.SetMaxIdleConns(1000) +// db.Ping() +// SqlDB = &*db +// GetDb() +//} + +//复制返回数组 +func DeepCopyMap(value interface{}) interface{} { + if valueMap, ok := value.(Map); ok { + newMap := make(Map) + for k, v := range valueMap { + newMap[k] = DeepCopyMap(v) + } + + return newMap + } else if valueSlice, ok := value.([]interface{}); ok { + newSlice := make([]interface{}, len(valueSlice)) + for k, v := range valueSlice { + newSlice[k] = DeepCopyMap(v) + } + + return newSlice + } else if valueMap, ok := value.(map[string]interface{}); ok { + newMap := make(map[string]interface{}) + for k, v := range valueMap { + newMap[k] = DeepCopyMap(v) + } + + return newMap + + } else if valueSlice, ok := value.(Slice); ok { + newSlice := make(Slice, len(valueSlice)) + for k, v := range valueSlice { + newSlice[k] = DeepCopyMap(v) + } + + return newSlice + } + + return value +} + +////获取数据库 +//func GetDb() (HoTimeDB, error) { +// Db.DB = &*SqlDB +// Db.Cached = true +// return Db, nil +//} + +//初始化方法 +//func Init() { +// +// http.HandleFunc("/", PublicCore.myHandler) +// +// InitCache() +// http.ListenAndServe(":"+Config["port"].(string), nil) +//} + +////设置Config +//func SetCfg(tData Map) { +// for k, v := range tData { +// Config[k] = v +// } +//} + +//浮点数四舍五入保留小数 +func Round(f float64, n int) float64 { + pow10_n := math.Pow10(n) + return math.Trunc((f+0.5/pow10_n)*pow10_n) / pow10_n +} + +//func InitDbCache(tim int64) { +// res := Db.Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='" + Config.GetString("dbName") + "' AND TABLE_NAME='cached'") +// if len(res) == 0 { +// Db.Exec("CREATE TABLE `cached` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `ckey` varchar(60) DEFAULT NULL, `cvalue` varchar(2000) DEFAULT NULL, `time` bigint(20) DEFAULT NULL, `endtime` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=198740 DEFAULT CHARSET=utf8") +// } +// cacheConfig := Config.GetMap("cacheConfig").GetObj("db").(CacheConfg) +// cacheConfig.Used = true +// if tim != 0 { +// cacheConfig.Time = tim +// } +// Config.GetMap("cacheConfig")["db"] = cacheConfig +//} +// +//func Cache(key interface{}, data ...interface{}) interface{} { +// cachePRI := Config["cachePRI"].([]string) +// var res interface{} +// for i := 0; i < len(cachePRI); i++ { +// if cachePRI[i] == "ridis" && Config["cacheConfig"].(Map)["ridis"].(CacheConfg).Used { +// res = CacheMemIns.Cache(ObjToStr(key), data...) +// } +// if cachePRI[i] == "db" && Config["cacheConfig"].(Map)["db"].(CacheConfg).Used { +// res = CacheDBIns.Cache(ObjToStr(key), data...) +// } +// if cachePRI[i] == "memory" && Config["cacheConfig"].(Map)["memory"].(CacheConfg).Used { +// res = CacheMemIns.Cache(ObjToStr(key), data...) +// } +// //将缓存送到前面的可缓存仓库去 +// if res != nil { +// for j := 0; j < i; j++ { +// if cachePRI[j] == "ridis" && Config["cacheConfig"].(Map)["ridis"].(CacheConfg).Used { +// CacheMemIns.Cache(ObjToStr(key), res) +// } +// if cachePRI[j] == "db" && Config["cacheConfig"].(Map)["db"].(CacheConfg).Used { +// CacheDBIns.Cache(ObjToStr(key), res) +// } +// if cachePRI[j] == "memory" && Config["cacheConfig"].(Map)["memory"].(CacheConfg).Used { +// CacheMemIns.Cache(ObjToStr(key), res) +// } +// +// } +// break +// } +// +// } +// return res +//} + +//func InitCache() { +// CacheMemIns.Init(Config["cacheConfig"].(Map)["memory"].(CacheConfg).Time) +// CacheDBIns.Init(Config["cacheConfig"].(Map)["db"].(CacheConfg).Time) +//} + diff --git a/map.go b/map.go new file mode 100644 index 0000000..9a298f5 --- /dev/null +++ b/map.go @@ -0,0 +1,145 @@ +package hotime + +import ( + "encoding/json" + "errors" + "reflect" +) + +//hotime的常用map +type Map map[string]interface{} + +//获取string +func (this Map) GetString(key string, err ...*Error) string { + + if len(err) != 0 { + err[0].SetError(nil) + } + return ObjToStr((this)[key]) + +} + +func (this *Map) Pointer() *Map{ + + return this +} + +//增加接口 +func (this Map) Put(key string, value interface{}) { + //if this==nil{ + // this=Map{} + //} + this[key] = value +} + +//删除接口 +func (this Map) Delete(key string) { + delete(this, key) + + + + +} + +//获取Int +func (this Map) GetInt(key string, err ...*Error) int { + v := ObjToInt((this)[key], err...) + + return v + + +} + +//获取Int +func (this Map) GetInt64(key string, err ...*Error) int64 { + v := ObjToInt64((this)[key], err...) + return v + + +} + +//获取Float64 +func (this Map) GetFloat64(key string, err ...*Error) float64 { + + v := ObjToFloat64((this)[key], err...) + + return v + +} + +func (this Map) GetSlice(key string, err ...*Error) Slice { + + //var v Slice + v := ObjToSlice((this)[key], err...) + + return v + + + +} + +func (this Map) GetMap(key string, err ...*Error) Map { + //var data Slice + + v := ObjToMap((this)[key], err...) + + return v + + + +} + +func (this Map) Get(key string, err ...*Error) interface{} { + + if v, ok := (this)[key]; ok { + return v + } + e := errors.New("没有存储key及对应的数据") + + if len(err) != 0 { + err[0].SetError(e) + + } + return nil +} + +//请传递指针过来 +func (this Map) ToStruct(stct interface{}) { + + data := reflect.ValueOf(stct).Elem() + for k, v := range this { + ks := StrFirstToUpper(k) + dkey := data.FieldByName(ks) + if !dkey.IsValid() { + continue + } + switch dkey.Type().String() { + case "int": + dkey.SetInt(this.GetInt64(k)) + case "int64": + dkey.Set(reflect.ValueOf(this.GetInt64(k))) + case "float64": + dkey.Set(reflect.ValueOf(this.GetFloat64(k))) + case "string": + dkey.Set(reflect.ValueOf(this.GetString(k))) + case "interface{}": + dkey.Set(reflect.ValueOf(v)) + } + } + + + +} + +func (this Map) ToJsonString() string { + return ObjToStr(this) + +} + +func (this Map) JsonToMap(jsonStr string,err... *Error) { + e:=json.Unmarshal([]byte(jsonStr), &this) + if e!=nil&&len(err)!=0{ + err[0].SetError(e) + } + +} diff --git a/obj.go b/obj.go new file mode 100644 index 0000000..35f8468 --- /dev/null +++ b/obj.go @@ -0,0 +1,55 @@ +package hotime + +type Obj struct { + Data interface{} + Error +} + +func (this *Obj) Put(data interface{}) { + this.Data = data +} + +func (this *Obj) ToInt(err ...Error) int { + if len(err) != 0 { + this.Error = err[0] + } + return ObjToInt(this.Data, &this.Error) +} + +func (this *Obj) ToInt64(err ...Error) int64 { + if len(err) != 0 { + this.Error = err[0] + } + return ObjToInt64(this.Data, &this.Error) +} + +func (this *Obj) ToFloat64(err ...Error) float64 { + if len(err) != 0 { + this.Error = err[0] + } + return ObjToFloat64(this.Data, &this.Error) +} + +func (this *Obj) ToStr() string { + + return ObjToStr(this.Data) +} + +func (this *Obj) ToMap(err ...Error) Map { + if len(err) != 0 { + this.Error = err[0] + } + return ObjToMap(this.Data, &this.Error) +} + +func (this *Obj) ToSlice(err ...Error) Slice { + if len(err) != 0 { + this.Error = err[0] + } + return ObjToSlice(this.Data, &this.Error) +} + +func (this *Obj) ToObj() interface{} { + + return this.Data +} diff --git a/objtoobj.go b/objtoobj.go new file mode 100644 index 0000000..94c3191 --- /dev/null +++ b/objtoobj.go @@ -0,0 +1,226 @@ +package hotime + +import ( + "errors" + "strconv" + "encoding/json" +) + +//仅限于hotime.Slice +func ObjToMap(obj interface{},e... *Error) Map { + var err error + var v Map + + if obj == nil { + v = nil + err = errors.New("没有合适的转换对象!") + } else { + switch obj.(type){ + case Map:v = obj.(Map) + case map[string]interface {}:v=obj.(map[string]interface{}) + default: + v = nil + err = errors.New("没有合适的转换对象!") + } + } + if(len(e)!=0){ + e[0].SetError(err) + } + return v +} + +//仅限于hotime.Slice +func ObjToSlice(obj interface{},e... *Error) Slice{ + var err error + var v Slice + + if obj == nil { + v = nil + err = errors.New("没有合适的转换对象!") + } else { + switch obj.(type) { + case Slice: + v = obj.(Slice) + case []interface {}:v=obj.([]interface{}) + default: + v = nil + err = errors.New("没有合适的转换对象!") + } + } + + if(len(e)!=0){ + e[0].SetError(err) + } + + return v +} + +func ObjToFloat64(obj interface{},e... *Error) float64 { + var err error + v := float64(0) + + if obj == nil { + + err = errors.New("没有合适的转换对象!") + } else { + + switch obj.(type) { + case int: + v = float64(obj.(int)) + case int64: + v = float64(obj.(int64)) + case string: + value, e := strconv.ParseFloat(obj.(string), 64) + if e != nil { + v = float64(0) + err = e + } else { + v = value + } + case float64: + v = obj.(float64) + case float32: + v = float64(obj.(float32)) + case uint8: + value, e := strconv.ParseFloat(obj.(string), 64) + if e != nil { + v = float64(0) + err = e + } else { + v = value + } + default: + v = float64(0) + err = errors.New("没有合适的转换对象!") + } + } + if(len(e)!=0){ + e[0].SetError(err) + } + return v +} + +func ObjToInt64(obj interface{},e... *Error) int64 { + var err error + v := int64(0) + + if obj == nil { + + err = errors.New("没有合适的转换对象!") + } else { + switch obj.(type) { + case int: + v = int64(obj.(int)) + case int64: + v = obj.(int64) + case string: + value, e := StrToInt(obj.(string)) + if e != nil { + v = int64(0) + err = e + } else { + v = int64(value) + } + case uint8: + value, e := StrToInt(obj.(string)) + if e != nil { + v = int64(0) + err = e + } else { + v = int64(value) + } + case float64: + v = int64(obj.(float64)) + case float32: + v = int64(obj.(float32)) + default: + v = int64(0) + err = errors.New("没有合适的转换对象!") + } + } + if(len(e)!=0){ + e[0].SetError(err) + } + return v +} + +func ObjToInt(obj interface{},e... *Error) int { + var err error + v := 0 + if obj == nil { + + err = errors.New("没有合适的转换对象!") + } else { + switch obj.(type) { + case int: + v = obj.(int) + case int64: + v = int(obj.(int64)) + case string: + value, e := StrToInt(obj.(string)) + if e != nil { + v = 0 + err = e + } else { + v = value + } + case uint8: + value, e := StrToInt(obj.(string)) + if e != nil { + v = 0 + err = e + } else { + v = value + } + case float64: + v = int(obj.(float64)) + case float32: + v = int(obj.(float32)) + default: + v = 0 + err = errors.New("没有合适的转换对象!") + + } + } + if(len(e)!=0){ + e[0].SetError(err) + } + return v +} + +func ObjToStr(obj interface{}) string { + // fmt.Println(reflect.ValueOf(obj).Type().String() ) + str := "" + if obj==nil{ + return str + } + switch obj.(type) { + case int: + str = strconv.Itoa(obj.(int)) + case uint8: + str = obj.(string) + case int64: + str = strconv.FormatInt(obj.(int64), 10) + case []byte: + str = string(obj.([]byte)) + case string: + str = obj.(string) + case float64: + str = strconv.FormatFloat(obj.(float64), 'f', 6, 64) + default: + strbte,err:=json.Marshal(obj); + if err==nil{ + str=string(strbte) + } + + } + + return str +} + +//字符串转int +func StrToInt(s string) (int, error) { + i, err := strconv.Atoi(s) + return i, err + +} \ No newline at end of file diff --git a/session.go b/session.go new file mode 100644 index 0000000..6952e31 --- /dev/null +++ b/session.go @@ -0,0 +1,75 @@ +package hotime + + +type SessionIns struct { + ShortCache CacheIns + LongCache CacheIns + SessionId string + Map + Error +} + +func (this *SessionIns)set(){ + + if this.ShortCache!=nil{ + this.ShortCache.Cache(SESSION_TYPE+this.SessionId,this.Map) + } + if this.LongCache!=nil{ + this.LongCache.Cache(SESSION_TYPE+this.SessionId,this.Map) + } + + +} + + +func(this *SessionIns)Session(key string,data ...interface{})*Obj{ + + if this.Map==nil{ + this.get() + } + + if len(data)!=0{ + if data[0]==nil{ + delete(this.Map,key) + this.set() + }else{ + this.Map[key]=data[0] + this.set() + } + return &Obj{Data:nil} + } + + return &Obj{Data:this.Map.Get(key)} + +} + +func (this *SessionIns)get(){ + + if this.ShortCache!=nil{ + this.Map=this.ShortCache.Cache(SESSION_TYPE+this.SessionId).ToMap() + if this.Map!=nil{ + return + } + } + + if this.LongCache!=nil{ + this.Map=this.LongCache.Cache(SESSION_TYPE+this.SessionId).ToMap() + if this.Map!=nil{ + if this.ShortCache!=nil{ + this.ShortCache.Cache(SESSION_TYPE+this.SessionId,this.Map) + } + return + } + } + this.Map=Map{} + this.ShortCache.Cache(SESSION_TYPE+this.SessionId,this.Map) + + return +} + + + +func (this *SessionIns)Init(short CacheIns, long CacheIns){ + this.ShortCache=short + this.LongCache=long +} \ No newline at end of file diff --git a/slice.go b/slice.go new file mode 100644 index 0000000..f577ed3 --- /dev/null +++ b/slice.go @@ -0,0 +1,80 @@ +package hotime + +import ("encoding/json" + "errors") + +type Slice []interface{} + +//获取string +func (this Slice) GetString(key int,err... *Error) string { + if(len(err)!=0){ + err[0].SetError(nil) + } + return ObjToStr((this)[key]) +} + +//获取Int +func (this Slice) GetInt(key int,err... *Error) int { + v := ObjToInt((this)[key],err...) + return v +} + +//获取Int +func (this Slice) GetInt64(key int,err... *Error) int64 { + v:= ObjToInt64((this)[key],err...) + + return v +} + +//获取Float64 +func (this Slice) GetFloat64(key int,err... *Error) (float64) { + v:= ObjToFloat64((this)[key],err...) + + return v +} + +func (this Slice) GetSlice(key int,err... *Error) Slice { + v := ObjToSlice((this)[key],err...) + return v +} + + +func (this Slice) GetMap(key int,err... *Error) Map { + //var v Map + v:= ObjToMap((this)[key],err...) + return v +} + + + +func (this Slice) Get(key int,err... *Error) interface{} { + + if(key