mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
gjson包改进,功能修复中
This commit is contained in:
34
g/container/gtype/byte.go
Normal file
34
g/container/gtype/byte.go
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
package gtype
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type Byte struct {
|
||||
val int32
|
||||
}
|
||||
|
||||
func NewByte(value...byte) *Byte {
|
||||
if len(value) > 0 {
|
||||
return &Byte{val : int32(value[0])}
|
||||
}
|
||||
return &Byte{}
|
||||
}
|
||||
|
||||
func (t *Byte)Set(value byte) {
|
||||
atomic.StoreInt32(&t.val, int32(value))
|
||||
}
|
||||
|
||||
func (t *Byte)Val() byte {
|
||||
return byte(atomic.LoadInt32(&t.val))
|
||||
}
|
||||
|
||||
func (t *Byte)Add(delta int) byte {
|
||||
return byte(atomic.AddInt32(&t.val, int32(delta)))
|
||||
}
|
||||
@ -4,7 +4,8 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// JSON解析/封装
|
||||
// JSON解析/封装.
|
||||
// 单元测试请参考gpaser包.
|
||||
package gjson
|
||||
|
||||
import (
|
||||
@ -20,12 +21,58 @@ import (
|
||||
"gitee.com/johng/gf/g/encoding/gtoml"
|
||||
)
|
||||
|
||||
const (
|
||||
gDEFAULT_SPLIT_CHAR = '.' // 默认层级分隔符号
|
||||
)
|
||||
|
||||
// json解析结果存放数组
|
||||
type Json struct {
|
||||
mu sync.RWMutex
|
||||
p *interface{} // 注意这是一个指针
|
||||
c byte // 层级分隔符,默认为"."
|
||||
vc bool // 是否执行分隔符冲突检测(默认为true,检测会比较影响检索效率)
|
||||
}
|
||||
|
||||
// 将变量转换为Json对象进行处理,该变量至少应当是一个map或者array,否者转换没有意义
|
||||
func New(value interface{}) *Json {
|
||||
switch value.(type) {
|
||||
case map[string]interface{}:
|
||||
return &Json{
|
||||
p : &value,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : true ,
|
||||
}
|
||||
case []interface{}:
|
||||
return &Json{
|
||||
p : &value,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : true ,
|
||||
}
|
||||
default:
|
||||
// 这里效率会比较低
|
||||
b, _ := Encode(value)
|
||||
v, _ := Decode(b)
|
||||
return &Json{
|
||||
p : &v,
|
||||
c : byte(gDEFAULT_SPLIT_CHAR),
|
||||
vc : true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置自定义的层级分隔符号
|
||||
func (j *Json) SetSplitChar(char byte) {
|
||||
j.mu.Lock()
|
||||
j.c = char
|
||||
j.mu.Unlock()
|
||||
}
|
||||
|
||||
// 设置自定义的层级分隔符号
|
||||
func (j *Json) SetViolenceCheck(check bool) {
|
||||
j.mu.Lock()
|
||||
j.vc = check
|
||||
j.mu.Unlock()
|
||||
}
|
||||
// 编码go变量为json字符串,并返回json字符串指针
|
||||
func Encode (v interface{}) ([]byte, error) {
|
||||
return json.Marshal(v)
|
||||
@ -51,7 +98,7 @@ func DecodeToJson (b []byte) (*Json, error) {
|
||||
if v, err := Decode(b); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return NewJson(v), nil
|
||||
return New(v), nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,26 +141,11 @@ func LoadContent (data []byte, t string) (*Json, error) {
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewJson(result), nil
|
||||
}
|
||||
|
||||
// 将变量转换为Json对象进行处理,该变量至少应当是一个map或者array,否者转换没有意义
|
||||
func NewJson(value interface{}) *Json {
|
||||
switch value.(type) {
|
||||
case map[string]interface{}:
|
||||
return &Json{ p: &value }
|
||||
case []interface{}:
|
||||
return &Json{ p: &value }
|
||||
default:
|
||||
// 这里效率会比较低
|
||||
b, _ := Encode(value)
|
||||
v, _ := Decode(b)
|
||||
return &Json{ p: &v }
|
||||
}
|
||||
return New(result), nil
|
||||
}
|
||||
|
||||
// 将指定的json内容转换为指定结构返回,查找失败或者转换失败,目标对象转换为nil
|
||||
// 注意第二个参数需要给的是变量地址
|
||||
// 注意第二个参数需要给的是**变量地址**
|
||||
func (j *Json) GetToVar(pattern string, v interface{}) error {
|
||||
r := j.Get(pattern)
|
||||
if r != nil {
|
||||
@ -144,7 +176,7 @@ func (j *Json) GetMap(pattern string) map[string]interface{} {
|
||||
func (j *Json) GetJson(pattern string) *Json {
|
||||
result := j.Get(pattern)
|
||||
if result != nil {
|
||||
return NewJson(result)
|
||||
return New(result)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -199,27 +231,22 @@ func (j *Json) Remove(pattern string) error {
|
||||
|
||||
// 根据pattern查找并设置数据
|
||||
// 注意:
|
||||
// 1、写入的时候"."符号只能表示层级,不能使用带"."符号的键名;
|
||||
// 2、写入的value为nil且removed为true时,表示删除;
|
||||
// 3、里面的层级处理比较复杂,逻辑较复杂的地方在于层级检索及节点创建,叶子赋值;
|
||||
// 1、写入的value为nil且removed为true时,表示删除;
|
||||
// 2、里面的层级处理比较复杂,逻辑较复杂的地方在于层级检索及节点创建,叶子赋值;
|
||||
func (j *Json) setValue(pattern string, value interface{}, removed bool) error {
|
||||
array := strings.Split(pattern, string(j.c))
|
||||
length := len(array)
|
||||
value = j.convertValue(value)
|
||||
// 初始化判断
|
||||
if *j.p == nil {
|
||||
if isNumeric(pattern) {
|
||||
if isNumeric(array[0]) {
|
||||
*j.p = make([]interface{}, 0)
|
||||
} else {
|
||||
*j.p = make(map[string]interface{})
|
||||
}
|
||||
}
|
||||
var pparent *interface{}
|
||||
var pointer *interface{}
|
||||
|
||||
pointer = j.p
|
||||
pparent = nil
|
||||
value = j.convertValue(value)
|
||||
array := strings.Split(pattern, ".")
|
||||
length := len(array)
|
||||
|
||||
var pparent *interface{} = nil // 父级元素项(设置时需要根据子级的内容确定数据类型,所以必须记录父级)
|
||||
var pointer *interface{} = j.p // 当前操作层级项
|
||||
j.mu.Lock()
|
||||
for i:= 0; i < length; i++ {
|
||||
switch (*pointer).(type) {
|
||||
@ -403,13 +430,31 @@ func (j *Json) setPointerWithValue(pointer *interface{}, key string, value inter
|
||||
func (j *Json) Get(pattern string) interface{} {
|
||||
j.mu.RLock()
|
||||
defer j.mu.RUnlock()
|
||||
if r := j.getPointerByPattern(pattern); r != nil {
|
||||
return *r
|
||||
|
||||
var result *interface{}
|
||||
if j.vc {
|
||||
result = j.getPointerByPattern(pattern)
|
||||
} else {
|
||||
result = j.getPointerByPatternWithoutSplitCharViolenceCheck(pattern)
|
||||
}
|
||||
if result != nil {
|
||||
return *result
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 根据pattern层级查找变量指针
|
||||
// 根据pattern层级查找**变量指针**
|
||||
// 检索方式:例如检索 a.a.a ,值为1
|
||||
// 1. 检索 a.a.a.a 是否存在对应map的键名;
|
||||
// 2. 检索 a.a.a 是否存在对应map的键名;
|
||||
// 3. 检索 a.a 是否存在对应map的键名;
|
||||
// 4. 检索 a 是否存在对应map的键名,如果检索出这是一个map,假如为变量m1;
|
||||
// 5. 在m1中检索 a.a.a 否存在对应map的键名;
|
||||
// 6. 在m1中检索 a.a 否存在对应map的键名;
|
||||
// 7. 在m1中检索 a 否存在对应map的键名,如果检索出这是一个map,假如为变量m2;
|
||||
// 8. 在m2中检索 a.a 否存在对应map的键名;
|
||||
// 9. 在m2中检索 a 否存在对应map的键名,检索到有值,值为1;
|
||||
// 这样检索的复杂度很高,主要是为了避免键名中存在分隔符号(默认为".")的情况,避免歧义。
|
||||
func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
||||
index := len(pattern)
|
||||
start := 0
|
||||
@ -432,7 +477,8 @@ func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
||||
pointer = r
|
||||
}
|
||||
} else {
|
||||
index = strings.LastIndex(pattern[start:index], ".")
|
||||
// 查找下一个分割符号的索引位置
|
||||
index = strings.LastIndexByte(pattern[start:index], j.c)
|
||||
if index != -1 && length > 0 {
|
||||
index += length + 1
|
||||
}
|
||||
@ -444,17 +490,38 @@ func (j *Json) getPointerByPattern(pattern string) *interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断给定的pattern在当前的pointer下是否有值,并返回对应的pointer
|
||||
// 层级检索,内部不执行分隔符冲突检查,检索效率会有所提高,但是冲突需要开发者自己根据自定义的分隔符来进行解决
|
||||
func (j *Json) getPointerByPatternWithoutSplitCharViolenceCheck(pattern string) *interface{} {
|
||||
pointer := j.p
|
||||
if len(pattern) == 0 {
|
||||
return pointer
|
||||
}
|
||||
array := strings.Split(pattern, string(j.c))
|
||||
for k, v := range array {
|
||||
if r := j.checkPatternByPointer(v, pointer); r != nil {
|
||||
if k == len(array) - 1 {
|
||||
return r
|
||||
} else {
|
||||
pointer = r
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断给定的key在当前的pointer下是否有值,并返回对应的pointer
|
||||
// 注意这里返回的指针都是临时变量的内存地址
|
||||
func (j *Json) checkPatternByPointer(pattern string, pointer *interface{}) *interface{} {
|
||||
func (j *Json) checkPatternByPointer(key string, pointer *interface{}) *interface{} {
|
||||
switch (*pointer).(type) {
|
||||
case map[string]interface{}:
|
||||
if v, ok := (*pointer).(map[string]interface{})[pattern]; ok {
|
||||
if v, ok := (*pointer).(map[string]interface{})[key]; ok {
|
||||
return &v
|
||||
}
|
||||
case []interface{}:
|
||||
if isNumeric(pattern) {
|
||||
n, err := strconv.Atoi(pattern)
|
||||
if isNumeric(key) {
|
||||
n, err := strconv.Atoi(key)
|
||||
if err == nil && len((*pointer).([]interface{})) > n {
|
||||
return &(*pointer).([]interface{})[n]
|
||||
}
|
||||
|
||||
@ -20,9 +20,9 @@ type Parser struct {
|
||||
// 该参数为非必需参数,默认为创建一个空的Parser对象
|
||||
func New (values...interface{}) *Parser {
|
||||
if len(values) > 0 {
|
||||
return &Parser{gjson.NewJson(values[0])}
|
||||
return &Parser{gjson.New(values[0])}
|
||||
}
|
||||
return &Parser{gjson.NewJson(nil)}
|
||||
return &Parser{gjson.New(nil)}
|
||||
}
|
||||
|
||||
func Load (path string) (*Parser, error) {
|
||||
|
||||
@ -156,6 +156,19 @@ func Test_Set9(t *testing.T) {
|
||||
}
|
||||
|
||||
|
||||
func Test_Set10(t *testing.T) {
|
||||
e := []byte(`{"a":{"b":{"c":1}}`)
|
||||
p := gparser.New(nil)
|
||||
p.Set("a.b.c", 1)
|
||||
if c, err := p.ToJson(); err == nil {
|
||||
fmt.Println(string(c))
|
||||
if bytes.Compare(c, e) != 0 {
|
||||
t.Error("expect:", string(e))
|
||||
}
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -25,8 +25,7 @@ const (
|
||||
gHTTP_METHODS = "GET,POST,DELETE,PUT,PATCH,HEAD,CONNECT,OPTIONS,TRACE"
|
||||
gDEFAULT_SERVER = "default"
|
||||
gDEFAULT_DOMAIN = "default"
|
||||
gDEFAULT_METHOD = "all"
|
||||
|
||||
gDEFAULT_METHOD = "ALL"
|
||||
gDEFAULT_COOKIE_PATH = "/" // 默认path
|
||||
gDEFAULT_COOKIE_MAX_AGE = 86400*365 // 默认cookie有效期(一年)
|
||||
gDEFAULT_SESSION_MAX_AGE = 600 // 默认session有效期(600秒)
|
||||
@ -35,15 +34,17 @@ const (
|
||||
|
||||
// http server结构体
|
||||
type Server struct {
|
||||
hmu sync.RWMutex // handlerMap互斥锁
|
||||
hmmu sync.RWMutex // handlerMap互斥锁
|
||||
htmu sync.RWMutex // handlerTree互斥锁
|
||||
name string // 服务名称,方便识别
|
||||
server http.Server // 底层http server对象
|
||||
config ServerConfig // 配置对象
|
||||
status int8 // 当前服务器状态(0:未启动,1:运行中)
|
||||
handlerMap HandlerMap // 所有注册的回调函数
|
||||
methodsMap map[string]bool // 所有支持的HTTP Method(初始化时自动填充)
|
||||
closeQueue *gqueue.Queue // 请求结束的关闭队列(存放的是需要异步关闭处理的*Request对象)
|
||||
handlerMap HandlerMap // 所有注册的回调函数(静态匹配)
|
||||
handlerTree map[string]interface{} // 所有注册的回调函数(动态匹配,树型+链表优先级匹配)
|
||||
hooksMap *gmap.StringInterfaceMap // 钩子注册方法map,键值为按照注册顺序生成的glist,用于hook顺序调用
|
||||
closeQueue *gqueue.Queue // 请求结束的关闭队列(存放的是需要异步关闭处理的*Request对象)
|
||||
servedCount *gtype.Int // 已经服务的请求数(4-8字节,不考虑溢出情况)
|
||||
cookieMaxAge *gtype.Int // Cookie有效期
|
||||
sessionMaxAge *gtype.Int // Session有效期
|
||||
@ -54,13 +55,17 @@ type Server struct {
|
||||
}
|
||||
|
||||
// 域名、URI与回调函数的绑定记录表
|
||||
type HandlerMap map[string]HandlerItem
|
||||
type HandlerMap map[string]*HandlerItem
|
||||
|
||||
// http回调函数注册信息
|
||||
type HandlerItem struct {
|
||||
ctype reflect.Type // 控制器类型
|
||||
fname string // 回调方法名称
|
||||
faddr HandlerFunc // 准确的执行方法内存地址(与以上两个参数二选一)
|
||||
ctype reflect.Type // 控制器类型
|
||||
fname string // 回调方法名称
|
||||
faddr HandlerFunc // 准确的执行方法内存地址(与以上两个参数二选一)
|
||||
uri string // 注册时的pattern - uri
|
||||
method string // 注册时的pattern - method
|
||||
domain string // 注册时的pattern - domain
|
||||
priority int // 优先级,用于链表排序,值越大优先级越高
|
||||
}
|
||||
|
||||
// http注册函数
|
||||
@ -81,11 +86,12 @@ func GetServer(names...string) (*Server) {
|
||||
}
|
||||
s := &Server {
|
||||
name : name,
|
||||
handlerMap : make(HandlerMap),
|
||||
methodsMap : make(map[string]bool),
|
||||
handlerMap : make(HandlerMap),
|
||||
handlerTree : make(map[string]interface{}),
|
||||
hooksMap : gmap.NewStringInterfaceMap(),
|
||||
servedCount : gtype.NewInt(),
|
||||
closeQueue : gqueue.New(),
|
||||
hooksMap : gmap.NewStringInterfaceMap(),
|
||||
routers : gcache.New(),
|
||||
cookies : gmap.NewIntInterfaceMap(),
|
||||
sessions : gcache.New(),
|
||||
@ -136,9 +142,16 @@ func (s *Server) handlerKey(domain, method, pattern string) string {
|
||||
}
|
||||
|
||||
// 注册服务处理方法
|
||||
func (s *Server) setHandler(domain, method, pattern string, item HandlerItem) {
|
||||
s.hmu.Lock()
|
||||
defer s.hmu.Unlock()
|
||||
func (s *Server) setHandler(pattern string, item *HandlerItem) error {
|
||||
domain, method, uri, err := s.parsePatternForBindHandler(pattern)
|
||||
if err != nil {
|
||||
return errors.New("invalid pattern")
|
||||
}
|
||||
item.uri = uri
|
||||
item.domain = domain
|
||||
item.method = method
|
||||
// 静态注册
|
||||
s.hmmu.Lock()
|
||||
if method == gDEFAULT_METHOD {
|
||||
for v, _ := range s.methodsMap {
|
||||
s.handlerMap[s.handlerKey(domain, v, pattern)] = item
|
||||
@ -146,7 +159,36 @@ func (s *Server) setHandler(domain, method, pattern string, item HandlerItem) {
|
||||
} else {
|
||||
s.handlerMap[s.handlerKey(domain, method, pattern)] = item
|
||||
}
|
||||
s.hmmu.Unlock()
|
||||
// 动态注册,首先需要判断是否是动态注册,如果不是那么就没必要添加到动态注册记录变量中
|
||||
if s.isUriHasRule(uri) {
|
||||
array := strings.Split(uri, "/")
|
||||
item.priority = len(array)
|
||||
pattern := ""
|
||||
for _, v := range array {
|
||||
switch v[0] {
|
||||
case ':':
|
||||
case '*':
|
||||
default:
|
||||
if p == nil {
|
||||
p = make(map[string]interface{})
|
||||
p = p.(map[string]interface{})
|
||||
}
|
||||
if _, ok := p[v]; !ok {
|
||||
p[v] = make(map[string]interface{})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 判断URI中是否包含动态注册规则
|
||||
func (s *Server) isUriHasRule(uri string) bool {
|
||||
if len(uri) > 1 && (strings.Index(uri, "/:") != -1 || strings.Index(uri, "/*") != -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 解析pattern
|
||||
@ -171,16 +213,11 @@ func (s *Server)parsePatternForBindHandler(pattern string) (domain, method, uri
|
||||
// 绑定URI到操作函数/方法
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user, post:/user@johng.cn
|
||||
// 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行
|
||||
func (s *Server)bindHandlerItem(pattern string, item HandlerItem) error {
|
||||
func (s *Server)bindHandlerItem(pattern string, item *HandlerItem) error {
|
||||
if s.status == 1 {
|
||||
return errors.New("server handlers cannot be changed while running")
|
||||
}
|
||||
domain, method, uri, err := s.parsePatternForBindHandler(pattern)
|
||||
if err != nil {
|
||||
return errors.New("invalid pattern")
|
||||
}
|
||||
s.setHandler(domain, method, uri, item)
|
||||
return nil
|
||||
return s.setHandler(pattern, item)
|
||||
}
|
||||
|
||||
// 通过映射数组绑定URI到操作函数/方法
|
||||
@ -216,7 +253,11 @@ func (s *Server)appendMethodNameToUriWithPattern(pattern string, name string) st
|
||||
|
||||
// 注意该方法是直接绑定函数的内存地址,执行的时候直接执行该方法,不会存在初始化新的控制器逻辑
|
||||
func (s *Server)BindHandler(pattern string, handler HandlerFunc) error {
|
||||
return s.bindHandlerItem(pattern, HandlerItem{nil, "", handler})
|
||||
return s.bindHandlerItem(pattern, &HandlerItem{
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : handler,
|
||||
})
|
||||
}
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
||||
@ -228,7 +269,11 @@ func (s *Server)BindObject(pattern string, obj interface{}) error {
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
name := t.Method(i).Name
|
||||
key := s.appendMethodNameToUriWithPattern(pattern, name)
|
||||
m[key] = HandlerItem{nil, "", v.Method(i).Interface().(func(*Request))}
|
||||
m[key] = &HandlerItem{
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
@ -244,7 +289,11 @@ func (s *Server)BindObjectMethod(pattern string, obj interface{}, methods string
|
||||
return errors.New("invalid method name:" + method)
|
||||
}
|
||||
key := s.appendMethodNameToUriWithPattern(pattern, method)
|
||||
m[key] = HandlerItem{nil, "", fval.Interface().(func(*Request))}
|
||||
m[key] = &HandlerItem{
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : fval.Interface().(func(*Request)),
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
@ -261,7 +310,11 @@ func (s *Server)BindObjectRest(pattern string, obj interface{}) error {
|
||||
continue
|
||||
}
|
||||
key := name + ":" + pattern
|
||||
m[key] = HandlerItem{nil, "", v.Method(i).Interface().(func(*Request))}
|
||||
m[key] = &HandlerItem{
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
@ -279,7 +332,11 @@ func (s *Server)BindController(pattern string, c Controller) error {
|
||||
continue
|
||||
}
|
||||
key := s.appendMethodNameToUriWithPattern(pattern, name)
|
||||
m[key] = HandlerItem{v.Elem().Type(), name, nil}
|
||||
m[key] = &HandlerItem{
|
||||
ctype : v.Elem().Type(),
|
||||
fname : name,
|
||||
faddr : nil,
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
@ -297,16 +354,21 @@ func (s *Server)BindControllerRest(pattern string, c Controller) error {
|
||||
for _, v := range strings.Split(gHTTP_METHODS, ",") {
|
||||
methods[v] = true
|
||||
}
|
||||
// 如果存在与HttpMethod对应名字的方法,那么绑定这些方法
|
||||
for i := 0; i < v.NumMethod(); i++ {
|
||||
name := t.Method(i).Name
|
||||
name := strings.ToUpper(t.Method(i).Name)
|
||||
if name == "Init" || name == "Shut" {
|
||||
continue
|
||||
}
|
||||
if _, ok := s.methodsMap[strings.ToUpper(name)]; !ok {
|
||||
if _, ok := s.methodsMap[name]; !ok {
|
||||
continue
|
||||
}
|
||||
key := name + ":" + pattern
|
||||
m[key] = HandlerItem{v.Elem().Type(), name, nil}
|
||||
m[key] = &HandlerItem{
|
||||
ctype : v.Elem().Type(),
|
||||
fname : name,
|
||||
faddr : nil,
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
@ -323,31 +385,35 @@ func (s *Server)BindControllerMethod(pattern string, c Controller, methods strin
|
||||
return errors.New("invalid method name:" + method)
|
||||
}
|
||||
key := s.appendMethodNameToUriWithPattern(pattern, method)
|
||||
m[key] = HandlerItem{ctype, method, nil}
|
||||
m[key] = &HandlerItem{
|
||||
ctype : ctype,
|
||||
fname : method,
|
||||
faddr : nil,
|
||||
}
|
||||
}
|
||||
return s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
// 绑定指定的hook回调函数, pattern参数同BindHandler,支持命名路由;hook参数的值由ghttp server设定,参数不区分大小写
|
||||
func (s *Server)BindHookHandler(pattern string, hook string, handler HandlerFunc) error {
|
||||
domain, method, uri, err := s.parsePatternForBindHandler(pattern)
|
||||
if err != nil {
|
||||
return errors.New("invalid pattern")
|
||||
}
|
||||
var l *glist.List
|
||||
if method == gDEFAULT_METHOD {
|
||||
for v, _ := range s.methodsMap {
|
||||
if v := s.hooksMap.GetWithDefault(s.handlerHookKey(domain, v, uri, hook), glist.New()); v != nil {
|
||||
l = v.(*glist.List)
|
||||
}
|
||||
l.PushBack(handler)
|
||||
}
|
||||
} else {
|
||||
if v := s.hooksMap.GetWithDefault(s.handlerHookKey(domain, method, uri, hook), glist.New()); v == nil {
|
||||
l = v.(*glist.List)
|
||||
}
|
||||
l.PushBack(handler)
|
||||
}
|
||||
//domain, method, uri, err := s.parsePatternForBindHookHandler(pattern)
|
||||
//if err != nil {
|
||||
// return errors.New("invalid pattern")
|
||||
//}
|
||||
//var l *glist.List
|
||||
//if method == gDEFAULT_METHOD {
|
||||
// for v, _ := range s.methodsMap {
|
||||
// if v := s.hooksMap.GetWithDefault(s.handlerHookKey(domain, v, uri, hook), glist.New()); v != nil {
|
||||
// l = v.(*glist.List)
|
||||
// }
|
||||
// l.PushBack(handler)
|
||||
// }
|
||||
//} else {
|
||||
// if v := s.hooksMap.GetWithDefault(s.handlerHookKey(domain, method, uri, hook), glist.New()); v == nil {
|
||||
// l = v.(*glist.List)
|
||||
// }
|
||||
// l.PushBack(handler)
|
||||
//}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
"gitee.com/johng/gf/g/os/gtime"
|
||||
)
|
||||
|
||||
func getByPattern() {
|
||||
@ -95,6 +96,67 @@ func testConvert() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func testSplitChar() {
|
||||
var v interface{}
|
||||
j := gjson.New(nil)
|
||||
t1 := gtime.Nanosecond()
|
||||
j.Set("a.b.c", 1)
|
||||
t2 := gtime.Nanosecond()
|
||||
fmt.Println(t2 - t1)
|
||||
|
||||
t5 := gtime.Nanosecond()
|
||||
v = j.Get("a.b.c.d.e.f.g.h.i.j.k")
|
||||
t6 := gtime.Nanosecond()
|
||||
b, _ := j.ToJsonIndent()
|
||||
fmt.Println(string(b))
|
||||
fmt.Println(v)
|
||||
fmt.Println(t6 - t5)
|
||||
|
||||
j.SetSplitChar('#')
|
||||
|
||||
|
||||
|
||||
t7 := gtime.Nanosecond()
|
||||
v = j.Get("a#a#a#a#a#a#a#a#a#a#a#a#a#a#a#a")
|
||||
t8 := gtime.Nanosecond()
|
||||
fmt.Println(v)
|
||||
fmt.Println(t8 - t7)
|
||||
}
|
||||
|
||||
|
||||
func testViolenceCheck() {
|
||||
j := gjson.New(nil)
|
||||
t1 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t2 := gtime.Nanosecond()
|
||||
fmt.Println(t2 - t1)
|
||||
|
||||
t3 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t4 := gtime.Nanosecond()
|
||||
fmt.Println(t4 - t3)
|
||||
|
||||
t5 := gtime.Nanosecond()
|
||||
j.Get("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a")
|
||||
t6 := gtime.Nanosecond()
|
||||
fmt.Println(t6 - t5)
|
||||
|
||||
|
||||
j.SetViolenceCheck(false)
|
||||
|
||||
|
||||
t7 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t8 := gtime.Nanosecond()
|
||||
fmt.Println(t8 - t7)
|
||||
|
||||
t9 := gtime.Nanosecond()
|
||||
j.Get("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a")
|
||||
t10 := gtime.Nanosecond()
|
||||
fmt.Println(t10 - t9)
|
||||
}
|
||||
|
||||
func main() {
|
||||
testSet()
|
||||
testSplitChar()
|
||||
}
|
||||
@ -1,16 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/util/gregx"
|
||||
"gitee.com/johng/gf/g/os/gtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
t1 := gtime.Microsecond()
|
||||
for i := 0; i < 10000; i++ {
|
||||
gregx.MatchString(`([a-zA-Z]+)\^([a-zA-Z]+):(.+)@([\w\.\-]+)`, "a^b:c@d")
|
||||
}
|
||||
t2 := gtime.Microsecond()
|
||||
j := gjson.New(nil)
|
||||
t1 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t2 := gtime.Nanosecond()
|
||||
fmt.Println(t2 - t1)
|
||||
|
||||
t3 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t4 := gtime.Nanosecond()
|
||||
fmt.Println(t4 - t3)
|
||||
|
||||
t5 := gtime.Nanosecond()
|
||||
j.Get("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a")
|
||||
t6 := gtime.Nanosecond()
|
||||
fmt.Println(t6 - t5)
|
||||
|
||||
|
||||
j.SetViolenceCheck(false)
|
||||
|
||||
|
||||
t7 := gtime.Nanosecond()
|
||||
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
|
||||
t8 := gtime.Nanosecond()
|
||||
fmt.Println(t8 - t7)
|
||||
|
||||
t9 := gtime.Nanosecond()
|
||||
j.Get("a.a")
|
||||
t10 := gtime.Nanosecond()
|
||||
fmt.Println(t10 - t9)
|
||||
}
|
||||
Reference in New Issue
Block a user