From 15c5d5b93b596e4ce2c4929972d48469e27899e0 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 15 Apr 2018 10:30:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E8=BF=9Bgconv=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E5=AE=8C=E5=96=84gconv=E7=A4=BA=E4=BE=8B=EF=BC=8CREAD?= =?UTF-8?q?ME=20updates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.MD | 87 ++++++++++++++++-------------- g/database/gdb/gdb_base.go | 6 +-- g/database/gdb/gdb_transaction.go | 6 +-- g/net/ghttp/http_response.go | 18 ++++++- g/net/ghttp/http_server.go | 26 +++++++++ g/net/ghttp/http_server_hooks.go | 4 ++ g/net/ghttp/http_server_router.go | 4 ++ g/util/gconv/gconv.go | 88 ++++++++++++++++++++++++------- g/util/gvalid/gvalid.go | 6 +-- geg/net/ghttp/hello.go | 29 +++------- geg/net/ghttp/router.go | 22 ++++++-- geg/other/test.go | 12 ++--- geg/util/gconv.go | 26 +++++++++ 13 files changed, 227 insertions(+), 107 deletions(-) create mode 100644 geg/util/gconv.go diff --git a/README.MD b/README.MD index 8d284ebf0..f8609507a 100644 --- a/README.MD +++ b/README.MD @@ -11,7 +11,7 @@ ## 介绍 gf(Go Frame)是一款为Web服务及网络服务开发设计的,模块化、低耦合、轻量级、高性能的Go语言开发框架。 实现了通用的HTTP/TCP/UDP Server,并提供了Web服务开发的系列核心组件, -包括:MVC、Cookie、Session、模板引擎、路由控制、配置管理、数据校验、数据库操作(ORM)等等, +包括:MVC、Cookie、Session、服务注册、路由控制、配置管理、模板引擎、数据校验、数据库操作(ORM)等等, 并且提供了数十个实用开发模块,包括:缓存模块、日志模块、JSON模块、命令行模块、二进制模块、环境变量模块、并发安全容器、Goroutine池等等。 gf是开源的,免费的,基于MIT协议进行分发,开源项目地址(gitee与github仓库保持实时同步): @@ -28,6 +28,48 @@ gf是开源的,免费的,基于MIT协议进行分发,开源项目地址(gi 1. 丰富详尽的框架文档及专业的技术支持/讨论群,易于使用及维护; 1. 更多特点请查阅框架手册( http://gf.johng.cn ); +## 文档 +* [框架介绍](http://gf.johng.cn/494364) +* [加入团队](http://gf.johng.cn/512841) +* [Web服务开发](http://gf.johng.cn/494647) + * [开始使用](http://gf.johng.cn/494366) + * [开发模式](http://gf.johng.cn/494367) + * [服务注册](http://gf.johng.cn/494368) + * [路由控制](http://gf.johng.cn/49437) + * [Cookie](http://gf.johng.cn/494372) + * [Session](http://gf.johng.cn/494373) + * [输入输出](http://gf.johng.cn/494374) + * [配置管理](http://gf.johng.cn/494376) + * [单例管理](http://gf.johng.cn/494377) + * [数据校验](http://gf.johng.cn/494378) + * [模板引擎](http://gf.johng.cn/494379) + * [数据库ORM](http://gf.johng.cn/494380) +* [网络服务开发](http://gf.johng.cn/494648) + * [TCPServer](http://gf.johng.cn/494382) + * [UDPServer](http://gf.johng.cn/494383) +* [功能模块设计](http://gf.johng.cn/494384) + * [缓存模块](http://gf.johng.cn/494385) + * [日志模块](http://gf.johng.cn/494386) + * [时间模块](http://gf.johng.cn/494387) + * [JSON模块](http://gf.johng.cn/494388) + * [命令行模块](http://gf.johng.cn/494389) + * [二进制模块](http://gf.johng.cn/500342) + * [HTTP客户端](http://gf.johng.cn/499674) + * [Goroutine池](http://gf.johng.cn/504458) + * [数据编码解析](http://gf.johng.cn/511393) + * [环境变量模块](http://gf.johng.cn/494390) + * [文件管理模块](http://gf.johng.cn/494391) + * [并发安全容器](http://gf.johng.cn/494392) + * [通用编码模块](http://gf.johng.cn/494393) + * [其他模块介绍](http://gf.johng.cn/494394) + + +## 贡献 +gf是开源的、免费的软件,这意味着任何人都可以为其开发和进步贡献力量。 +gf的项目源代码目前同时托管在 Gitee 和 Github 平台上,您可以选择您喜欢的平台来 fork 项目和合并你的贡献, +两个平台的仓库将会保持即时的同步。我们非常欢迎有更多的朋友加入到gf框架的开发中来, +您为gf所做出的任何贡献都将会被记录到gf的史册中。 + ## 安装 ``` go get -u gitee.com/johng/gf @@ -176,7 +218,7 @@ go get -u gitee.com/johng/gf r.Response.Write(r.Get("name")) r.Response.Write(r.Get("action")) }) - s.BindHandler("/:name/:any", func(r *ghttp.Request){ + s.BindHandler("/:name/*any", func(r *ghttp.Request){ r.Response.Write(r.Get("name")) r.Response.Write(r.Get("any")) }) @@ -301,41 +343,8 @@ go get -u gitee.com/johng/gf ``` -## 文档 -* [框架介绍](http://gf.johng.cn/494364) -* [加入团队](http://gf.johng.cn/512841) -* [Web服务开发](http://gf.johng.cn/494647) - * [WebServer](http://gf.johng.cn/494366) - * [MVC模式](http://gf.johng.cn/494367) - * [服务注册](http://gf.johng.cn/494368) - * [Cookie](http://gf.johng.cn/494372) - * [Session](http://gf.johng.cn/494373) - * [输入输出](http://gf.johng.cn/494374) - * [路由控制](http://gf.johng.cn/49437) - * [配置管理](http://gf.johng.cn/494376) - * [单例管理](http://gf.johng.cn/494377) - * [数据校验](http://gf.johng.cn/494378) - * [模板引擎](http://gf.johng.cn/494379) - * [数据库ORM](http://gf.johng.cn/494380) -* [网络服务开发](http://gf.johng.cn/494648) - * [TCPServer](http://gf.johng.cn/494382) - * [UDPServer](http://gf.johng.cn/494383) -* [功能模块设计](http://gf.johng.cn/494384) - * [缓存模块](http://gf.johng.cn/494385) - * [日志模块](http://gf.johng.cn/494386) - * [时间模块](http://gf.johng.cn/494387) - * [JSON模块](http://gf.johng.cn/494388) - * [命令行模块](http://gf.johng.cn/494389) - * [二进制模块](http://gf.johng.cn/500342) - * [HTTP客户端](http://gf.johng.cn/499674) - * [Goroutine池](http://gf.johng.cn/504458) - * [数据编码解析](http://gf.johng.cn/511393) - * [环境变量模块](http://gf.johng.cn/494390) - * [文件管理模块](http://gf.johng.cn/494391) - * [并发安全容器](http://gf.johng.cn/494392) - * [通用编码模块](http://gf.johng.cn/494393) - * [其他模块介绍](http://gf.johng.cn/494394) +... + + +更多特性及示例请查看官方开发文档:[gf.johng.cn](http://gf.johng.cn) - -## 贡献 -gf是开源的、免费的软件,这意味着任何人都可以为其开发和进步贡献力量。gf的项目源代码目前同时托管在 Gitee 和 Github 平台上,您可以选择您喜欢的平台来 fork 项目和合并你的贡献,两个平台的仓库将会保持即时的同步。我们非常欢迎有更多的朋友加入到gf框架的开发中来,您为gf所做出的任何贡献都将会被记录到gf的史册中。 \ No newline at end of file diff --git a/g/database/gdb/gdb_base.go b/g/database/gdb/gdb_base.go index bc5e8c615..9f4fcf127 100644 --- a/g/database/gdb/gdb_base.go +++ b/g/database/gdb/gdb_base.go @@ -295,12 +295,12 @@ func (db *Db) BatchSave(table string, list List, batch int) (sql.Result, error) func (db *Db) Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) { var params []interface{} var updates string - switch data.(type) { + switch value := data.(type) { case string: - updates = data.(string) + updates = value case Map: var keys []string - for k, v := range data.(Map) { + for k, v := range value { keys = append(keys, fmt.Sprintf("%s%s%s=?", db.charl, k, db.charr)) params = append(params, v) } diff --git a/g/database/gdb/gdb_transaction.go b/g/database/gdb/gdb_transaction.go index e871eba2a..12a8d5153 100644 --- a/g/database/gdb/gdb_transaction.go +++ b/g/database/gdb/gdb_transaction.go @@ -232,12 +232,12 @@ func (tx *Tx) BatchSave(table string, list List, batch int) (sql.Result, error) func (tx *Tx) Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) { var params []interface{} var updates string - switch data.(type) { + switch value := data.(type) { case string: - updates = data.(string) + updates = value case Map: var keys []string - for k, v := range data.(Map) { + for k, v := range value { keys = append(keys, fmt.Sprintf("%s%s%s=?", tx.db.charl, k, tx.db.charr)) params = append(params, v) } diff --git a/g/net/ghttp/http_response.go b/g/net/ghttp/http_response.go index d3046a273..17f5252a6 100644 --- a/g/net/ghttp/http_response.go +++ b/g/net/ghttp/http_response.go @@ -22,12 +22,26 @@ type Response struct { } // 返回信息,任何变量自动转换为bytes -func (r *Response) Write(content interface{}) { +func (r *Response) Write(content ... interface{}) { + if len(content) == 0 { + return + } r.bufmu.Lock() - r.buffer = append(r.buffer, gconv.Bytes(content)...) + for _, v := range content { + r.buffer = append(r.buffer, gconv.Bytes(v)...) + } r.bufmu.Unlock() } +// 返回信息,末尾增加换行标识符"\n" +func (r *Response) Writeln(content ... interface{}) { + if len(content) == 0 { + return + } + content = append(content, "\n") + r.Write(content...) +} + // 返回JSON func (r *Response) WriteJson(content interface{}) error { if b, err := gparser.VarToJson(content); err != nil { diff --git a/g/net/ghttp/http_server.go b/g/net/ghttp/http_server.go index 574ac7794..a474d03b6 100644 --- a/g/net/ghttp/http_server.go +++ b/g/net/ghttp/http_server.go @@ -33,6 +33,8 @@ const ( type Server struct { hmmu sync.RWMutex // handler互斥锁 hhmu sync.RWMutex // hooks互斥锁 + hmcmu sync.RWMutex // handlerCache互斥锁 + hhcmu sync.RWMutex // hooksCache互斥锁 name string // 服务名称,方便识别 server http.Server // 底层http server对象 config ServerConfig // 配置对象 @@ -135,4 +137,28 @@ func (s *Server) Run() error { } s.status = 1 return nil +} + +// 清空当前的handlerCache +func (s *Server) clearHandlerCache() { + // 只有在运行时才会生效 + if s.status != 1 { + return + } + s.hmcmu.Lock() + defer s.hmcmu.Unlock() + s.handlerCache.Close() + s.handlerCache = gcache.New() +} + +// 清空当前的hooksCache +func (s *Server) clearHooksCache() { + // 只有在运行时才会生效 + if s.status != 1 { + return + } + s.hhcmu.Lock() + defer s.hhcmu.Unlock() + s.hooksCache.Close() + s.hooksCache = gcache.New() } \ No newline at end of file diff --git a/g/net/ghttp/http_server_hooks.go b/g/net/ghttp/http_server_hooks.go index 7c57216b2..01a077d14 100644 --- a/g/net/ghttp/http_server_hooks.go +++ b/g/net/ghttp/http_server_hooks.go @@ -32,6 +32,7 @@ func (s *Server) setHookHandler(pattern string, hook string, item *HandlerItem) s.hhmu.Lock() defer s.hhmu.Unlock() + defer s.clearHooksCache() if _, ok := s.hooksTree[domain]; !ok { s.hooksTree[domain] = make(map[string]interface{}) } @@ -86,6 +87,9 @@ func (s *Server) setHookHandler(pattern string, hook string, item *HandlerItem) // 事件回调 - 检索动态路由规则 // 并按照指定hook回调函数的优先级及注册顺序进行调用 func (s *Server) callHookHandler(r *Request, hook string) { + s.hhcmu.RLock() + defer s.hhcmu.RUnlock() + var hookItems []*hookCacheItem cacheKey := hook + "^" + r.URL.Path if v := s.hooksCache.Get(cacheKey); v == nil { diff --git a/g/net/ghttp/http_server_router.go b/g/net/ghttp/http_server_router.go index cbf4b50a4..bd8c1627c 100644 --- a/g/net/ghttp/http_server_router.go +++ b/g/net/ghttp/http_server_router.go @@ -23,6 +23,9 @@ type handlerCacheItem struct { // 查询请求处理方法 // 这里有个锁机制,可以并发读,但是不能并发写 func (s *Server) getHandler(r *Request) *HandlerItem { + s.hmcmu.RLock() + defer s.hmcmu.RUnlock() + var handlerItem *handlerCacheItem if v := s.handlerCache.Get(r.URL.Path); v == nil { handlerItem = s.searchHandler(r) @@ -72,6 +75,7 @@ func (s *Server) setHandler(pattern string, item *HandlerItem) error { // 静态注册 s.hmmu.Lock() defer s.hmmu.Unlock() + defer s.clearHandlerCache() if method == gDEFAULT_METHOD { for v, _ := range s.methodsMap { s.handlerMap[s.handlerKey(domain, v, uri)] = item diff --git a/g/util/gconv/gconv.go b/g/util/gconv/gconv.go index e181127a0..a59d01780 100644 --- a/g/util/gconv/gconv.go +++ b/g/util/gconv/gconv.go @@ -10,6 +10,7 @@ package gconv import ( "fmt" + "strconv" "gitee.com/johng/gf/g/encoding/gbinary" ) @@ -29,10 +30,22 @@ func String(i interface{}) string { if i == nil { return "" } - if r, ok := i.(string); ok { - return r - } else { - return string(Bytes(i)) + switch value := i.(type) { + case int: return strconv.Itoa(value) + case int8: return strconv.Itoa(int(value)) + case int16: return strconv.Itoa(int(value)) + case int32: return strconv.Itoa(int(value)) + case int64: return strconv.Itoa(int(value)) + case uint: return strconv.FormatUint(uint64(value), 10) + case uint8: return strconv.FormatUint(uint64(value), 10) + case uint16: return strconv.FormatUint(uint64(value), 10) + case uint32: return strconv.FormatUint(uint64(value), 10) + case uint64: return strconv.FormatUint(uint64(value), 10) + case bool: return strconv.FormatBool(value) + case string: return value + case []byte: return string(value) + default: + return fmt.Sprintf("%v", value) } } @@ -70,10 +83,26 @@ func Int(i interface{}) int { if i == nil { return 0 } - if v, ok := i.(int); ok { - return v + switch value := i.(type) { + case int: return value + case int8: return int(value) + case int16: return int(value) + case int32: return int(value) + case int64: return int(value) + case uint: return int(value) + case uint8: return int(value) + case uint16: return int(value) + case uint32: return int(value) + case uint64: return int(value) + case bool: + if value { + return 1 + } + return 0 + default: + v, _ := strconv.Atoi(String(value)) + return v } - return gbinary.DecodeToInt(Bytes(i)) } func Int8(i interface{}) int8 { @@ -83,7 +112,7 @@ func Int8(i interface{}) int8 { if v, ok := i.(int8); ok { return v } - return gbinary.DecodeToInt8(Bytes(i)) + return int8(Int(i)) } func Int16(i interface{}) int16 { @@ -93,7 +122,7 @@ func Int16(i interface{}) int16 { if v, ok := i.(int16); ok { return v } - return gbinary.DecodeToInt16(Bytes(i)) + return int16(Int(i)) } func Int32(i interface{}) int32 { @@ -103,7 +132,7 @@ func Int32(i interface{}) int32 { if v, ok := i.(int32); ok { return v } - return gbinary.DecodeToInt32(Bytes(i)) + return int32(Int(i)) } func Int64(i interface{}) int64 { @@ -113,17 +142,33 @@ func Int64(i interface{}) int64 { if v, ok := i.(int64); ok { return v } - return gbinary.DecodeToInt64(Bytes(i)) + return int64(Int(i)) } func Uint(i interface{}) uint { if i == nil { return 0 } - if v, ok := i.(uint); ok { - return v + switch value := i.(type) { + case int: return uint(value) + case int8: return uint(value) + case int16: return uint(value) + case int32: return uint(value) + case int64: return uint(value) + case uint: return value + case uint8: return uint(value) + case uint16: return uint(value) + case uint32: return uint(value) + case uint64: return uint(value) + case bool: + if value { + return 1 + } + return 0 + default: + v, _ := strconv.ParseUint(String(value), 10, 64) + return uint(v) } - return gbinary.DecodeToUint(Bytes(i)) } func Uint8(i interface{}) uint8 { @@ -133,7 +178,7 @@ func Uint8(i interface{}) uint8 { if v, ok := i.(uint8); ok { return v } - return gbinary.DecodeToUint8(Bytes(i)) + return uint8(Uint(i)) } func Uint16(i interface{}) uint16 { @@ -143,7 +188,7 @@ func Uint16(i interface{}) uint16 { if v, ok := i.(uint16); ok { return v } - return gbinary.DecodeToUint16(Bytes(i)) + return uint16(Uint(i)) } func Uint32(i interface{}) uint32 { @@ -153,7 +198,7 @@ func Uint32(i interface{}) uint32 { if v, ok := i.(uint32); ok { return v } - return gbinary.DecodeToUint32(Bytes(i)) + return uint32(Uint(i)) } func Uint64(i interface{}) uint64 { @@ -163,7 +208,7 @@ func Uint64(i interface{}) uint64 { if v, ok := i.(uint64); ok { return v } - return gbinary.DecodeToUint64(Bytes(i)) + return uint64(Uint(i)) } func Float32 (i interface{}) float32 { @@ -173,7 +218,8 @@ func Float32 (i interface{}) float32 { if v, ok := i.(float32); ok { return v } - return gbinary.DecodeToFloat32(Bytes(i)) + v, _ := strconv.ParseFloat(String(i), 32) + return float32(v) } func Float64 (i interface{}) float64 { @@ -183,5 +229,7 @@ func Float64 (i interface{}) float64 { if v, ok := i.(float64); ok { return v } - return gbinary.DecodeToFloat64(Bytes(i)) + v, _ := strconv.ParseFloat(String(i), 32) + return v } + diff --git a/g/util/gvalid/gvalid.go b/g/util/gvalid/gvalid.go index 858d88fed..eab2aa76d 100644 --- a/g/util/gvalid/gvalid.go +++ b/g/util/gvalid/gvalid.go @@ -424,11 +424,11 @@ func Check(val interface{}, rules string, msgs interface{}, params...map[string] // 自定义错误消息处理 list := make([]string, 0) cmsgs := make(map[string]string) - switch msgs.(type) { + switch value := msgs.(type) { case map[string]string: - cmsgs = msgs.(map[string]string) + cmsgs = value case string: - list = strings.Split(msgs.(string), "|") + list = strings.Split(value, "|") } items := strings.Split(strings.TrimSpace(rules), "|") for index := 0; index < len(items); { diff --git a/geg/net/ghttp/hello.go b/geg/net/ghttp/hello.go index 76da0a670..a7ff5c2d1 100644 --- a/geg/net/ghttp/hello.go +++ b/geg/net/ghttp/hello.go @@ -1,29 +1,12 @@ package main -import ( - "gitee.com/johng/gf/g/net/ghttp" -) +import "gitee.com/johng/gf/g/net/ghttp" func main() { - ghttp.GetServer().BindHandler("/", func(r *ghttp.Request) { - //r.Response.RedirectTo("http://www.baidu.com/") - r.Response.Write("哈喽世界!") - //r.Response.WriteStatus(302) + s := ghttp.GetServer() + s.BindHandler("/", func(r *ghttp.Request){ + r.Response.Writeln("哈喽世界!") }) - - //ghttp.GetServer().BindHandler("/:name/*any", func(r *ghttp.Request) { - // r.Response.Write("any") - // r.Response.Write(r.Get("name")) - // r.Response.Write(r.Get("any")) - //}) - ////ghttp.GetServer().BindHandler("/:name/action", func(r *ghttp.Request) { - //// r.Response.Write(r.Get("name")) - ////}) - //ghttp.GetServer().BindHandler("/:name/:action/:aaa", func(r *ghttp.Request) { - // r.Response.Write("name") - // r.Response.Write(r.Get("name")) - // r.Response.Write(r.Get("action")) - //}) - ghttp.GetServer().SetPort(10000) - ghttp.GetServer().Run() + s.SetPort(8199) + s.Run() } \ No newline at end of file diff --git a/geg/net/ghttp/router.go b/geg/net/ghttp/router.go index a0a14e3f0..0843c1d8b 100644 --- a/geg/net/ghttp/router.go +++ b/geg/net/ghttp/router.go @@ -2,10 +2,22 @@ package main import "gitee.com/johng/gf/g/net/ghttp" -func main () { - ghttp.GetServer().BindHandler("/router/*name", func(r *ghttp.Request) { - r.Response.Write(r.Get("name")) +func main() { + s := ghttp.GetServer() + s.BindHandler("/:name", func(r *ghttp.Request){ + r.Response.Writeln("pattern: /:name match") + r.Response.Writeln(r.Get("name")) }) - ghttp.GetServer().SetPort(10000) - ghttp.GetServer().Run() + s.BindHandler("/:name/:action", func(r *ghttp.Request){ + r.Response.Writeln("pattern: /:name/:action match") + r.Response.Writeln(r.Get("name")) + r.Response.Writeln(r.Get("action")) + }) + s.BindHandler("/:name/*any", func(r *ghttp.Request){ + r.Response.Writeln("pattern: /:name/*any match") + r.Response.Writeln(r.Get("name")) + r.Response.Writeln(r.Get("any")) + }) + s.SetPort(8199) + s.Run() } \ No newline at end of file diff --git a/geg/other/test.go b/geg/other/test.go index 233ca467f..6b3a395db 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -2,16 +2,10 @@ package main import ( "fmt" + "gitee.com/johng/gf/g/util/gconv" ) -type T struct{ - name string -} + func main() { - var i interface{} = T{"john"} - switch v := i.(type) { - case T: - default: - fmt.Println(v) - } + fmt.Println(gconv.Uint("123")) } \ No newline at end of file diff --git a/geg/util/gconv.go b/geg/util/gconv.go new file mode 100644 index 000000000..27d4dbe88 --- /dev/null +++ b/geg/util/gconv.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "gitee.com/johng/gf/g/util/gconv" +) + +func main() { + i := 123 + fmt.Printf("%10s %v\n", "Int:", gconv.Int(i)) + fmt.Printf("%10s %v\n", "Int8:", gconv.Int8(i)) + fmt.Printf("%10s %v\n", "Int16:", gconv.Int16(i)) + fmt.Printf("%10s %v\n", "Int32:", gconv.Int32(i)) + fmt.Printf("%10s %v\n", "Int64:", gconv.Int64(i)) + fmt.Printf("%10s %v\n", "Uint:", gconv.Uint(i)) + fmt.Printf("%10s %v\n", "Uint8:", gconv.Uint8(i)) + fmt.Printf("%10s %v\n", "Uint16:", gconv.Uint16(i)) + fmt.Printf("%10s %v\n", "Uint32:", gconv.Uint32(i)) + fmt.Printf("%10s %v\n", "Uint64:", gconv.Uint64(i)) + fmt.Printf("%10s %v\n", "Float32:", gconv.Float32(i)) + fmt.Printf("%10s %v\n", "Float64:", gconv.Float64(i)) + fmt.Printf("%10s %v\n", "Bool:", gconv.Bool(i)) + fmt.Printf("%10s %v\n", "Bytes:", gconv.Bytes(i)) + fmt.Printf("%10s %v\n", "String:", gconv.String(i)) + fmt.Printf("%10s %v\n", "Strings:", gconv.Strings(i)) +} \ No newline at end of file