From 5e9e1418a2d974275e7608b8838c26ff8421afd4 Mon Sep 17 00:00:00 2001 From: hoteas Date: Fri, 4 Aug 2017 08:20:59 +0000 Subject: [PATCH] --- .idea/hotime.iml | 9 + .idea/libraries/GOPATH__hotime_.xml | 33 + .idea/misc.xml | 31 + .idea/modules.xml | 8 + .idea/preferred-vcs.xml | 6 + .idea/vcs.xml | 6 + .idea/workspace.xml | 912 ++++++++++++++++++++++++++++ app.go | 247 ++++++++ cachedb.go | 107 ++++ cachememory.go | 93 +++ const.go | 18 + context.go | 68 +++ db.go | 807 ++++++++++++++++++++++++ error.go | 38 ++ func.go | 303 +++++++++ map.go | 145 +++++ obj.go | 55 ++ objtoobj.go | 226 +++++++ session.go | 75 +++ slice.go | 80 +++ type.go | 20 + var.go | 28 + 22 files changed, 3315 insertions(+) create mode 100644 .idea/hotime.iml create mode 100644 .idea/libraries/GOPATH__hotime_.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/preferred-vcs.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 app.go create mode 100644 cachedb.go create mode 100644 cachememory.go create mode 100644 const.go create mode 100644 context.go create mode 100644 db.go create mode 100644 error.go create mode 100644 func.go create mode 100644 map.go create mode 100644 obj.go create mode 100644 objtoobj.go create mode 100644 session.go create mode 100644 slice.go create mode 100644 type.go create mode 100644 var.go 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