diff --git a/g/encoding/gjson/gjson_api_new_load.go b/g/encoding/gjson/gjson_api_new_load.go index 04a4b3166..712a4dd51 100644 --- a/g/encoding/gjson/gjson_api_new_load.go +++ b/g/encoding/gjson/gjson_api_new_load.go @@ -136,7 +136,10 @@ func LoadContent(data interface{}, unsafe...bool) (*Json, error) { var err error var result interface{} b := gconv.Bytes(data) - t := "json" + t := "" + if len(b) == 0 { + return New(nil, unsafe...), nil + } // auto check data type if json.Valid(b) { t = "json" diff --git a/g/frame/gins/gins.go b/g/frame/gins/gins.go index 0794b6367..e055ac72d 100644 --- a/g/frame/gins/gins.go +++ b/g/frame/gins/gins.go @@ -219,13 +219,13 @@ func Redis(name...string) *gredis.Redis { Pass : array[4], }) } else { - glog.Errorfln(`invalid redis node configuration: "%s"`, line) + glog.Errorf(`invalid redis node configuration: "%s"`, line) } } else { - glog.Errorfln(`configuration for redis not found for group "%s"`, group) + glog.Errorf(`configuration for redis not found for group "%s"`, group) } } else { - glog.Errorfln(`incomplete configuration for redis: "redis" node not found in config file "%s"`, config.FilePath()) + glog.Errorf(`incomplete configuration for redis: "redis" node not found in config file "%s"`, config.FilePath()) } return nil }) diff --git a/g/net/ghttp/ghttp_server.go b/g/net/ghttp/ghttp_server.go index 13efff4da..aa32e5359 100644 --- a/g/net/ghttp/ghttp_server.go +++ b/g/net/ghttp/ghttp_server.go @@ -389,7 +389,7 @@ func (s *Server) Run() error { // 阻塞等待服务执行完成 <- s.closeChan - glog.Printfln("%d: all servers shutdown", gproc.Pid()) + glog.Printf("%d: all servers shutdown", gproc.Pid()) return nil } @@ -400,7 +400,7 @@ func Wait() { // 阻塞等待服务执行完成 <- allDoneChan - glog.Printfln("%d: all servers shutdown", gproc.Pid()) + glog.Printf("%d: all servers shutdown", gproc.Pid()) } diff --git a/g/net/ghttp/ghttp_server_admin_process.go b/g/net/ghttp/ghttp_server_admin_process.go index 70865c4d1..5b9c1057c 100644 --- a/g/net/ghttp/ghttp_server_admin_process.go +++ b/g/net/ghttp/ghttp_server_admin_process.go @@ -129,7 +129,7 @@ func forkReloadProcess(newExeFilePath...string) error { buffer, _ := gjson.Encode(sfm) p.Env = append(p.Env, gADMIN_ACTION_RELOAD_ENVKEY + "=" + string(buffer)) if _, err := p.Start(); err != nil { - glog.Errorfln("%d: fork process failed, error:%s, %s", gproc.Pid(), err.Error(), string(buffer)) + glog.Errorf("%d: fork process failed, error:%s, %s", gproc.Pid(), err.Error(), string(buffer)) return err } return nil @@ -147,7 +147,7 @@ func forkRestartProcess(newExeFilePath...string) error { env = append(env, gADMIN_ACTION_RESTART_ENVKEY + "=1") p := gproc.NewProcess(path, os.Args, env) if _, err := p.Start(); err != nil { - glog.Errorfln("%d: fork process failed, error:%s", gproc.Pid(), err.Error()) + glog.Errorf("%d: fork process failed, error:%s", gproc.Pid(), err.Error()) return err } return nil @@ -197,14 +197,14 @@ func restartWebServers(signal string, newExeFilePath...string) error { } } else { if err := forkReloadProcess(newExeFilePath...); err != nil { - glog.Printfln("%d: server restarts failed", gproc.Pid()) + glog.Printf("%d: server restarts failed", gproc.Pid()) serverProcessStatus.Set(gADMIN_ACTION_NONE) return err } else { if len(signal) > 0 { - glog.Printfln("%d: server restarting by signal: %s", gproc.Pid(), signal) + glog.Printf("%d: server restarting by signal: %s", gproc.Pid(), signal) } else { - glog.Printfln("%d: server restarting by web admin", gproc.Pid()) + glog.Printf("%d: server restarting by web admin", gproc.Pid()) } } @@ -216,12 +216,12 @@ func restartWebServers(signal string, newExeFilePath...string) error { func shutdownWebServers(signal...string) { serverProcessStatus.Set(gADMIN_ACTION_SHUTINGDOWN) if len(signal) > 0 { - glog.Printfln("%d: server shutting down by signal: %s", gproc.Pid(), signal[0]) + glog.Printf("%d: server shutting down by signal: %s", gproc.Pid(), signal[0]) // 在终端信号下,立即执行关闭操作 forceCloseWebServers() allDoneChan <- struct{}{} } else { - glog.Printfln("%d: server shutting down by api", gproc.Pid()) + glog.Printf("%d: server shutting down by api", gproc.Pid()) // 非终端信号下,异步1秒后再执行关闭, // 目的是让接口能够正确返回结果,否则接口会报错(因为web server关闭了) gtimer.SetTimeout(time.Second, func() { diff --git a/g/net/ghttp/ghttp_server_graceful.go b/g/net/ghttp/ghttp_server_graceful.go index 7ea854cd3..dbe99d32a 100644 --- a/g/net/ghttp/ghttp_server_graceful.go +++ b/g/net/ghttp/ghttp_server_graceful.go @@ -130,7 +130,7 @@ func (s *gracefulServer) doServe() error { if s.fd != 0 { action = "reloaded" } - glog.Printfln("%d: %s server %s listening on [%s]", gproc.Pid(), s.getProto(), action, s.addr) + glog.Printf("%d: %s server %s listening on [%s]", gproc.Pid(), s.getProto(), action, s.addr) s.status = SERVER_STATUS_RUNNING err := s.httpServer.Serve(s.listener) s.status = SERVER_STATUS_STOPPED @@ -173,7 +173,7 @@ func (s *gracefulServer) shutdown() { return } if err := s.httpServer.Shutdown(context.Background()); err != nil { - glog.Errorfln("%d: %s server [%s] shutdown error: %v", gproc.Pid(), s.getProto(), s.addr, err) + glog.Errorf("%d: %s server [%s] shutdown error: %v", gproc.Pid(), s.getProto(), s.addr, err) } } @@ -183,7 +183,7 @@ func (s *gracefulServer) close() { return } if err := s.httpServer.Close(); err != nil { - glog.Errorfln("%d: %s server [%s] closed error: %v", gproc.Pid(), s.getProto(), s.addr, err) + glog.Errorf("%d: %s server [%s] closed error: %v", gproc.Pid(), s.getProto(), s.addr, err) } } diff --git a/g/net/ghttp/ghttp_server_router.go b/g/net/ghttp/ghttp_server_router.go index c367e371f..c7838c793 100644 --- a/g/net/ghttp/ghttp_server_router.go +++ b/g/net/ghttp/ghttp_server_router.go @@ -84,7 +84,7 @@ func (s *Server) setHandler(pattern string, handler *handlerItem, hook ... strin caller := s.getHandlerRegisterCallerLine(handler) if len(hook) == 0 { if item, ok := s.routesMap[regkey]; ok { - glog.Errorfln(`duplicated route registry "%s", already registered at %s`, pattern, item[0].file) + glog.Errorf(`duplicated route registry "%s", already registered at %s`, pattern, item[0].file) return } } diff --git a/g/net/ghttp/ghttp_server_router_group.go b/g/net/ghttp/ghttp_server_router_group.go index 5e859d0f5..075645b4f 100644 --- a/g/net/ghttp/ghttp_server_router_group.go +++ b/g/net/ghttp/ghttp_server_router_group.go @@ -50,7 +50,7 @@ func (d *Domain) Group(prefix...string) *RouterGroup { func (g *RouterGroup) Bind(items []GroupItem) { for _, item := range items { if len(item) < 3 { - glog.Fatalfln("invalid router item: %s", item) + glog.Fatalf("invalid router item: %s", item) } if strings.EqualFold(gconv.String(item[0]), "REST") { g.bind("REST", gconv.String(item[0]) + ":" + gconv.String(item[1]), item[2]) @@ -124,7 +124,7 @@ func (g *RouterGroup) bind(bindType string, pattern string, object interface{}, if len(g.prefix) > 0 { domain, method, path, err := g.server.parsePattern(pattern) if err != nil { - glog.Fatalfln("invalid pattern: %s", pattern) + glog.Fatalf("invalid pattern: %s", pattern) } if bindType == "HANDLER" { pattern = g.server.serveHandlerKey(method, g.prefix + "/" + strings.TrimLeft(path, "/"), domain) @@ -196,7 +196,7 @@ func (g *RouterGroup) bind(bindType string, pattern string, object interface{}, g.domain.BindHookHandler(pattern, methods[0], h) } } else { - glog.Fatalfln("invalid hook handler for pattern:%s", pattern) + glog.Fatalf("invalid hook handler for pattern:%s", pattern) } } } diff --git a/g/net/ghttp/ghttp_server_service_controller.go b/g/net/ghttp/ghttp_server_service_controller.go index 994d4124f..b5058ab23 100644 --- a/g/net/ghttp/ghttp_server_service_controller.go +++ b/g/net/ghttp/ghttp_server_service_controller.go @@ -50,11 +50,11 @@ func (s *Server)BindController(pattern string, c Controller, methods...string) { if _, ok := v.Method(i).Interface().(func()); !ok { if len(methodMap) > 0 { // 指定的方法名称注册,那么需要使用错误提示 - glog.Errorfln(`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`, + glog.Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`, pkgPath, ctlName, mname, v.Method(i).Type().String()) } else { // 否则只是Debug提示 - glog.Debugfln(`ignore route method: %s.%s.%s defined as "%s", no match "func()"`, + glog.Debugf(`ignore route method: %s.%s.%s defined as "%s", no match "func()"`, pkgPath, ctlName, mname, v.Method(i).Type().String()) } continue @@ -108,7 +108,7 @@ func (s *Server)BindControllerMethod(pattern string, c Controller, method string ctlName = fmt.Sprintf(`(%s)`, ctlName) } if _, ok := fval.Interface().(func()); !ok { - glog.Errorfln(`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`, + glog.Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`, pkgPath, ctlName, mname, fval.Type().String()) return } @@ -147,7 +147,7 @@ func (s *Server)BindControllerRest(pattern string, c Controller) { ctlName = fmt.Sprintf(`(%s)`, ctlName) } if _, ok := v.Method(i).Interface().(func()); !ok { - glog.Errorfln(`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`, + glog.Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`, pkgPath, ctlName, mname, v.Method(i).Type().String()) return } diff --git a/g/net/ghttp/ghttp_server_service_object.go b/g/net/ghttp/ghttp_server_service_object.go index 74dcd8a32..5f07203de 100644 --- a/g/net/ghttp/ghttp_server_service_object.go +++ b/g/net/ghttp/ghttp_server_service_object.go @@ -57,11 +57,11 @@ func (s *Server)BindObject(pattern string, obj interface{}, methods...string) { if !ok { if len(methodMap) > 0 { // 指定的方法名称注册,那么需要使用错误提示 - glog.Errorfln(`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`, + glog.Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`, pkgPath, objName, mname, v.Method(i).Type().String()) } else { // 否则只是Debug提示 - glog.Debugfln(`ignore route method: %s.%s.%s defined as "%s", no match "func(*ghttp.Request)"`, + glog.Debugf(`ignore route method: %s.%s.%s defined as "%s", no match "func(*ghttp.Request)"`, pkgPath, objName, mname, v.Method(i).Type().String()) } continue @@ -127,7 +127,7 @@ func (s *Server)BindObjectMethod(pattern string, obj interface{}, method string) } faddr, ok := fval.Interface().(func(*Request)) if !ok { - glog.Errorfln(`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`, + glog.Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`, pkgPath, objName, mname, fval.Type().String()) return } @@ -174,7 +174,7 @@ func (s *Server)BindObjectRest(pattern string, obj interface{}) { } faddr, ok := v.Method(i).Interface().(func(*Request)) if !ok { - glog.Errorfln(`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`, + glog.Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`, pkgPath, objName, mname, v.Method(i).Type().String()) continue } diff --git a/g/os/gcfg/gcfg.go b/g/os/gcfg/gcfg.go index 70fcd6833..1233a3702 100644 --- a/g/os/gcfg/gcfg.go +++ b/g/os/gcfg/gcfg.go @@ -57,7 +57,7 @@ func New(file...string) *Config { if gfile.Exists(envPath) { c.SetPath(envPath) } else { - glog.Errorfln("Configuration directory path does not exist: %s", envPath) + glog.Errorf("Configuration directory path does not exist: %s", envPath) } } else { // Dir path of working dir. @@ -276,9 +276,9 @@ func (c *Config) getJson(file...string) *gjson.Json { return j } else { if filePath != "" { - glog.Criticalfln(`[gcfg] Load config file "%s" failed: %s`, filePath, err.Error()) + glog.Criticalf(`[gcfg] Load config file "%s" failed: %s`, filePath, err.Error()) } else { - glog.Criticalfln(`[gcfg] Load configuration failed: %s`, err.Error()) + glog.Criticalf(`[gcfg] Load configuration failed: %s`, err.Error()) } } return nil diff --git a/g/os/gcron/gcron_entry.go b/g/os/gcron/gcron_entry.go index ecc880089..b4c136e5b 100644 --- a/g/os/gcron/gcron_entry.go +++ b/g/os/gcron/gcron_entry.go @@ -115,7 +115,7 @@ func (entry *Entry) check() { return case STATUS_CLOSED: - glog.Path(path).Level(level).Debugfln("[gcron] %s(%s) %s removed", entry.Name, entry.schedule.pattern, entry.jobName) + glog.Path(path).Level(level).Debugf("[gcron] %s(%s) %s removed", entry.Name, entry.schedule.pattern, entry.jobName) entry.Close() case STATUS_READY: fallthrough @@ -130,12 +130,12 @@ func (entry *Entry) check() { if times < 2000000000 && times > 1000000000 { entry.times.Set(gDEFAULT_TIMES) } - glog.Path(path).Level(level).Debugfln("[gcron] %s(%s) %s start", entry.Name, entry.schedule.pattern, entry.jobName) + glog.Path(path).Level(level).Debugf("[gcron] %s(%s) %s start", entry.Name, entry.schedule.pattern, entry.jobName) defer func() { if err := recover(); err != nil { - glog.Path(path).Level(level).Errorfln("[gcron] %s(%s) %s end with error: %v", entry.Name, entry.schedule.pattern, entry.jobName, err) + glog.Path(path).Level(level).Errorf("[gcron] %s(%s) %s end with error: %v", entry.Name, entry.schedule.pattern, entry.jobName, err) } else { - glog.Path(path).Level(level).Debugfln("[gcron] %s(%s) %s end", entry.Name, entry.schedule.pattern, entry.jobName) + glog.Path(path).Level(level).Debugf("[gcron] %s(%s) %s end", entry.Name, entry.schedule.pattern, entry.jobName) } if entry.entry.Status() == STATUS_CLOSED { entry.Close() diff --git a/g/os/gmlock/gmlock.go b/g/os/gmlock/gmlock.go index ee785b27a..8bfcbbd6e 100644 --- a/g/os/gmlock/gmlock.go +++ b/g/os/gmlock/gmlock.go @@ -5,8 +5,6 @@ // You can obtain one at https://github.com/gogf/gf. // Package gmlock implements a thread-safe memory locker. -// -// 内存锁. package gmlock import "time" @@ -43,4 +41,14 @@ func RLock(key string) { // 解除基于内存锁的读锁 func RUnlock(key string) { locker.RUnlock(key) +} + +// 通过闭包的方式写锁执行回调方法,执行完毕后释放写锁 +func LockFunc(key string, f func(), expire...time.Duration) { + locker.LockFunc(key, f, expire...) +} + +// 通过闭包的方式读锁执行回调方法,执行完毕后释放读锁 +func RLockFunc(key string, f func()) { + locker.RLockFunc(key, f) } \ No newline at end of file diff --git a/g/os/gmlock/gmlock_locker.go b/g/os/gmlock/gmlock_locker.go index a43fb55e8..133a15053 100644 --- a/g/os/gmlock/gmlock_locker.go +++ b/g/os/gmlock/gmlock_locker.go @@ -58,6 +58,20 @@ func (l *Locker) RUnlock(key string) { } } +// 通过闭包的方式写锁执行回调方法,执行完毕后释放写锁 +func (l *Locker) LockFunc(key string, f func(), expire...time.Duration) { + l.Lock(key, expire...) + defer l.Unlock(key) + f() +} + +// 通过闭包的方式读锁执行回调方法,执行完毕后释放读锁 +func (l *Locker) RLockFunc(key string, f func()) { + l.RLock(key) + defer l.RUnlock(key) + f() +} + // 获得过期时间,没有设置时默认为0不过期 func (l *Locker) getExpire(expire...time.Duration) time.Duration { e := time.Duration(0) diff --git a/g/os/gview/gview.go b/g/os/gview/gview.go index 5d97f39aa..98957cef0 100644 --- a/g/os/gview/gview.go +++ b/g/os/gview/gview.go @@ -69,7 +69,7 @@ func New(path...string) *View { if gfile.Exists(envPath) { view.SetPath(envPath) } else { - glog.Errorfln("Template directory path does not exist: %s", envPath) + glog.Errorf("Template directory path does not exist: %s", envPath) } } else { // Dir path of working dir. diff --git a/g/os/gview/gview_doparse.go b/g/os/gview/gview_doparse.go index b122d977c..2dc12e0e9 100644 --- a/g/os/gview/gview_doparse.go +++ b/g/os/gview/gview_doparse.go @@ -15,6 +15,7 @@ import ( "github.com/gogf/gf/g/os/gfile" "github.com/gogf/gf/g/os/gfsnotify" "github.com/gogf/gf/g/os/glog" + "github.com/gogf/gf/g/os/gmlock" "github.com/gogf/gf/g/os/gspath" "github.com/gogf/gf/g/text/gstr" "text/template" @@ -40,7 +41,7 @@ func (view *View) getTemplate(path string, pattern string) (tpl *template.Templa if tpl, err = tpl.ParseFiles(files...); err != nil { return nil } - gfsnotify.Add(path, func(event *gfsnotify.Event) { + _, _ = gfsnotify.Add(path, func(event *gfsnotify.Event) { templates.Remove(path) gfsnotify.Exit() }) @@ -102,7 +103,9 @@ func (view *View) Parse(file string, params...Params) (parsed string, err error) if err != nil { return "", err } - tpl, err = tpl.Parse(gfcache.GetContents(path)) + gmlock.LockFunc("gview-template-parsing:" + folder, func() { + tpl, err = tpl.Parse(gfcache.GetContents(path)) + }) if err != nil { return "", err } diff --git a/geg/other/test.go b/geg/other/test.go index e9ed58c18..cd63d8660 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,10 +1,24 @@ package main import ( - "fmt" - "github.com/gogf/gf/g/os/gtime" + "github.com/gogf/gf/g" + "github.com/gogf/gf/g/net/ghttp" + "github.com/gogf/gf/g/os/gcache" ) func main() { - fmt.Println(gtime.Second()) + s := g.Server() + s.BindHandler("/", func(r *ghttp.Request) { + rs :="GF(Go Frame)是一款模块化、松耦合、生产级的Go应用开发框架。提供了常用的核心开发组件,如:缓存、日志、文件、时间、队列、数组、集合、字符串、定时器、命令行、文件锁、内存锁、对象池、连接池、数据校验、数据编码、文件监控、定时任务、数据库ORM、TCP/UDP组件、进程管理/通信、 并发安全容器等等。并提供了Web服务开发的系列核心组件,如:Router、Cookie、Session、路由注册、配置管理、模板引擎等等,支持热重启、热更新、多域名、多端口、多服务、HTTPS、Rewrite等特性。" + Weijin_word := gcache.Get("weijin_word") + if Weijin_word == nil { + Weijin_word = gcache.GetOrSet("weijin_word", rs, 0) + } + //此行压测会提示map并发错误 webbench -c 8000 -t 60 http://IP 局域网两台机器测试 + r.Response.WriteTpl("layout.html", g.Map{ + "Contentb": Weijin_word, + }) + }) + s.SetPort(8199) + s.Run() } \ No newline at end of file