From 34cb222b33679c7f9fe014b5829136ef3e230194 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 25 Apr 2019 22:14:20 +0800 Subject: [PATCH] remove temprary function map parameter for gview when parsing template file and content --- g/container/glist/glist.go | 4 + g/container/gqueue/gqueue.go | 53 ++++++------ g/container/gset/gset.go | 6 ++ g/frame/gmvc/view.go | 13 +-- g/net/ghttp/ghttp_response_view.go | 86 +++++-------------- g/net/ghttp/ghttp_server.go | 15 ++-- g/net/ghttp/ghttp_server_session.go | 2 +- g/os/gfile/gfile.go | 8 +- g/os/gview/gview_doparse.go | 43 ++++++---- g/util/gutil/gutil.go | 2 +- geg/net/ghttp/server/https/https_http.go | 5 +- .../template/build-in/objects/objects.go | 16 ++++ .../template/{ => build-in/vars}/config.toml | 0 .../vars/vars.go} | 9 +- geg/net/ghttp/server/template/tpl1/tpl1.go | 3 +- geg/net/ghttp/server/template/tpl2/main.go | 3 - geg/os/gview/layout/layout1/main.go | 14 ++- geg/other/test.go | 52 ++--------- version.go | 2 +- 19 files changed, 152 insertions(+), 184 deletions(-) create mode 100644 geg/net/ghttp/server/template/build-in/objects/objects.go rename geg/net/ghttp/server/template/{ => build-in/vars}/config.toml (100%) rename geg/net/ghttp/server/template/{buildin-vars.go => build-in/vars/vars.go} (59%) diff --git a/g/container/glist/glist.go b/g/container/glist/glist.go index e9c3a6080..ee62ca371 100644 --- a/g/container/glist/glist.go +++ b/g/container/glist/glist.go @@ -289,6 +289,10 @@ func (l *List) RemoveAll() { l.mu.Unlock() } +func (l *List) Clear() { + l.RemoveAll() +} + // 读锁操作 func (l *List) RLockFunc(f func(list *list.List)) { l.mu.RLock() diff --git a/g/container/gqueue/gqueue.go b/g/container/gqueue/gqueue.go index 79b9cfae5..d04584e80 100644 --- a/g/container/gqueue/gqueue.go +++ b/g/container/gqueue/gqueue.go @@ -4,14 +4,18 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// Package gqueue provides a dynamic/static concurrent-safe(alternative) queue. +// Package gqueue provides a dynamic/static concurrent-safe queue. // -// 并发安全动态队列. +// Features: +// +// 1. FIFO queue(data -> list -> chan); +// +// 2. Fast creation and initialization; +// +// 3. Support dynamic queue size(unlimited queue size); +// +// 4. Blocking when reading data from queue; // -// 特点: -// 1. 动态队列初始化速度快; -// 2. 动态的队列大小(不限大小); -// 3. 取数据时如果队列为空那么会阻塞等待; package gqueue import ( @@ -19,27 +23,21 @@ import ( "math" ) -// 1、这是一个先进先出的队列(chan <-- list); -// -// 2、当创建Queue对象时限定大小,那么等同于一个同步的chan并发安全队列; -// -// 3、不限制大小时,list链表用以存储数据,临时chan负责为客户端读取数据,当从chan获取数据时,list往chan中不停补充数据; -// -// 4、由于功能主体是chan,那么操作仍然像chan那样具有阻塞效果; type Queue struct { - limit int // 队列限制大小 - list *glist.List // 底层数据链表 - events chan struct{} // 写入事件通知 - closed chan struct{} // 队列关闭通知 - C chan interface{} // 队列数据读取 + limit int // Limit for queue size. + list *glist.List // Underlying list structure for data maintaining. + events chan struct{} // Events for data writing. + closed chan struct{} // Events for queue closing. + C chan interface{} // Underlying channel for data reading. } const ( - // 动态队列缓冲区大小 + // Size for queue buffer. gDEFAULT_QUEUE_SIZE = 10000 ) -// 队列大小为非必须参数,默认不限制 +// New returns a queue object. +// Param is optional and it is not limited by default. func New(limit...int) *Queue { q := &Queue { closed : make(chan struct{}, 0), @@ -56,7 +54,8 @@ func New(limit...int) *Queue { return q } -// 异步list->chan同步队列 +// startAsyncLoop starts an asynchronous goroutine, +// which handles the data synchronization from list to channel . func (q *Queue) startAsyncLoop() { for { select { @@ -84,7 +83,8 @@ func (q *Queue) startAsyncLoop() { } } -// 将数据压入队列, 队尾 +// Push pushes the data into the queue. +// Note that it would panics if the Push method is called after the queue is closed. func (q *Queue) Push(v interface{}) { if q.limit > 0 { q.C <- v @@ -94,19 +94,22 @@ func (q *Queue) Push(v interface{}) { } } -// 从队头先进先出地从队列取出一项数据 +// Pop pops an item from the queue in FIFO way. +// Note that it would return nil immediately if the Pop method is called after the queue is closed. func (q *Queue) Pop() interface{} { return <- q.C } -// 关闭队列(通知所有通过Pop*阻塞的协程退出) +// Close closes the queue. +// Notice: It would notify all goroutines exit immediately, +// which are blocked reading by Pop method). func (q *Queue) Close() { close(q.C) close(q.events) close(q.closed) } -// 获取当前队列大小 +// Size returns the length of the queue. func (q *Queue) Size() int { return len(q.C) + q.list.Len() } diff --git a/g/container/gset/gset.go b/g/container/gset/gset.go index 7344d62f3..3484d08b0 100644 --- a/g/container/gset/gset.go +++ b/g/container/gset/gset.go @@ -295,4 +295,10 @@ func (set *Set) Sum() (sum int) { sum += gconv.Int(k) } return +} + +// Join joins items with a string . +func (set *Set) Pops(size int) []interface{} { + array := make([]interface{}, 0, size) + return array } \ No newline at end of file diff --git a/g/frame/gmvc/view.go b/g/frame/gmvc/view.go index 719a1ef73..207f94916 100644 --- a/g/frame/gmvc/view.go +++ b/g/frame/gmvc/view.go @@ -18,7 +18,6 @@ type View struct { mu sync.RWMutex // 并发互斥锁 view *gview.View // 底层视图对象 data gview.Params // 视图数据/模板变量 - fmap gview.FuncMap // 绑定的模板函数 response *ghttp.Response // 数据返回对象 } @@ -27,7 +26,6 @@ func NewView(w *ghttp.Response) *View { return &View { view : gins.View(), data : make(gview.Params), - fmap : make(gview.FuncMap), response : w, } } @@ -48,18 +46,11 @@ func (view *View) Assign(key string, value interface{}) { view.mu.Unlock() } -// 绑定自定义模板函数 -func (view *View) BindFunc(name string, function interface{}){ - view.mu.Lock() - view.fmap[name] = function - view.mu.Unlock() -} - // 解析模板,并返回解析后的内容 func (view *View) Parse(file string) (string, error) { view.mu.RLock() defer view.mu.RUnlock() - buffer, err := view.response.ParseTpl(file, view.data, view.fmap) + buffer, err := view.response.ParseTpl(file, view.data) return buffer, err } @@ -67,7 +58,7 @@ func (view *View) Parse(file string) (string, error) { func (view *View) ParseContent(content string) (string, error) { view.mu.RLock() defer view.mu.RUnlock() - buffer, err := view.response.ParseTplContent(content, view.data, view.fmap) + buffer, err := view.response.ParseTplContent(content, view.data) return buffer, err } diff --git a/g/net/ghttp/ghttp_response_view.go b/g/net/ghttp/ghttp_response_view.go index 703a940bd..62ec7dd17 100644 --- a/g/net/ghttp/ghttp_response_view.go +++ b/g/net/ghttp/ghttp_response_view.go @@ -13,13 +13,9 @@ import ( ) // 展示模板,可以给定模板参数,及临时的自定义模板函数 -func (r *Response) WriteTpl(tpl string, params map[string]interface{}, funcMap...map[string]interface{}) error { - fmap := make(gview.FuncMap) - if len(funcMap) > 0 { - fmap = funcMap[0] - } - if b, err := r.ParseTpl(tpl, params, fmap); err != nil { - r.Write("Tpl Parsing Error: " + err.Error()) +func (r *Response) WriteTpl(tpl string, params...gview.Params) error { + if b, err := r.ParseTpl(tpl, params...); err != nil { + r.Write("Template Parsing Error: " + err.Error()) return err } else { r.Write(b) @@ -28,13 +24,9 @@ func (r *Response) WriteTpl(tpl string, params map[string]interface{}, funcMap.. } // 展示模板内容,可以给定模板参数,及临时的自定义模板函数 -func (r *Response) WriteTplContent(content string, params map[string]interface{}, funcMap...map[string]interface{}) error { - fmap := make(gview.FuncMap) - if len(funcMap) > 0 { - fmap = funcMap[0] - } - if b, err := r.ParseTplContent(content, params, fmap); err != nil { - r.Write("Tpl Parsing Error: " + err.Error()) +func (r *Response) WriteTplContent(content string, params...gview.Params) error { + if b, err := r.ParseTplContent(content, params...); err != nil { + r.Write("Template Parsing Error: " + err.Error()) return err } else { r.Write(b) @@ -43,61 +35,27 @@ func (r *Response) WriteTplContent(content string, params map[string]interface{} } // 解析模板文件,并返回模板内容 -func (r *Response) ParseTpl(tpl string, params gview.Params, funcMap...map[string]interface{}) (string, error) { - m := make(gview.FuncMap) - if len(funcMap) > 0 { - m = funcMap[0] - } - return gins.View().Parse(tpl, r.buildInVars(params), r.buildInFuncs(m)) +func (r *Response) ParseTpl(tpl string, params...gview.Params) (string, error) { + return gins.View().Parse(tpl, r.buildInVars(params...)) } // 解析并返回模板内容 -func (r *Response) ParseTplContent(content string, params gview.Params, funcMap...map[string]interface{}) (string, error) { - m := make(gview.FuncMap) - if len(funcMap) > 0 { - m = funcMap[0] - } - return gins.View().ParseContent(content, r.buildInVars(params), r.buildInFuncs(m)) +func (r *Response) ParseTplContent(content string, params...gview.Params) (string, error) { + return gins.View().ParseContent(content, r.buildInVars(params...)) } -// 内置变量 -func (r *Response) buildInVars(params map[string]interface{}) map[string]interface{} { - if params == nil { - params = make(map[string]interface{}) - } - c := gins.Config() - if c.GetFilePath() != "" { - params["Config"] = c.GetMap("") +// 内置变量/对象 +func (r *Response) buildInVars(params...map[string]interface{}) map[string]interface{} { + vars := map[string]interface{}(nil) + if len(params) > 0 { + vars = params[0] } else { - params["Config"] = nil + vars = make(map[string]interface{}) } - params["Cookie"] = r.request.Cookie.Map() - params["Session"] = r.request.Session.Data() - return params -} - -// 内置函数 -func (r *Response) buildInFuncs(funcMap map[string]interface{}) map[string]interface{} { - if funcMap == nil { - funcMap = make(map[string]interface{}) - } - funcMap["get"] = r.funcGet - funcMap["post"] = r.funcPost - funcMap["request"] = r.funcRequest - return funcMap -} - -// 模板内置函数: get -func (r *Response) funcGet(key string, def...string) string { - return r.request.GetQueryString(key, def...) -} - -// 模板内置函数: post -func (r *Response) funcPost(key string, def...string) string { - return r.request.GetPostString(key, def...) -} - -// 模板内置函数: request -func (r *Response) funcRequest(key string, def...string) string { - return r.request.Get(key, def...) + vars["Config"] = gins.Config().GetMap("") + vars["Cookie"] = r.request.Cookie.Map() + vars["Session"] = r.request.Session.Map() + vars["Get"] = r.request.GetQueryMap() + vars["Post"] = r.request.GetPostMap() + return vars } \ No newline at end of file diff --git a/g/net/ghttp/ghttp_server.go b/g/net/ghttp/ghttp_server.go index 80de109c3..5b2f64aa7 100644 --- a/g/net/ghttp/ghttp_server.go +++ b/g/net/ghttp/ghttp_server.go @@ -15,7 +15,8 @@ import ( "github.com/gogf/gf/g/container/gtype" "github.com/gogf/gf/g/os/gcache" "github.com/gogf/gf/g/os/genv" - "github.com/gogf/gf/g/os/glog" + "github.com/gogf/gf/g/os/gfile" + "github.com/gogf/gf/g/os/glog" "github.com/gogf/gf/g/os/gproc" "github.com/gogf/gf/g/os/gtimer" "github.com/gogf/gf/g/text/gregex" @@ -108,9 +109,9 @@ const ( HOOK_BEFORE_OUTPUT = "BeforeOutput" HOOK_AFTER_OUTPUT = "AfterOutput" - // deprecated. + // Deprecated. HOOK_BEFORE_CLOSE = "BeforeClose" - // deprecated. + // Deprecated. HOOK_AFTER_CLOSE = "AfterClose" HTTP_METHODS = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE" @@ -188,10 +189,10 @@ func serverProcessInit() { go handleProcessMessage() } - // 是否处于开发环境 - //if gfile.MainPkgPath() != "" { - // glog.Debug("GF notices that you're in develop environment, so error logs are auto enabled to stdout.") - //} + // 是否处于开发环境,这里调用该方法初始化main包路径值, + // 防止异步服务goroutine获取main包路径失败, + // 该方法只有在main协程中才会执行。 + gfile.MainPkgPath() } // 获取/创建一个默认配置的HTTP Server(默认监听端口是80) diff --git a/g/net/ghttp/ghttp_server_session.go b/g/net/ghttp/ghttp_server_session.go index 75e3fd091..61e29973c 100644 --- a/g/net/ghttp/ghttp_server_session.go +++ b/g/net/ghttp/ghttp_server_session.go @@ -69,7 +69,7 @@ func (s *Session) Id() string { } // 获取当前session所有数据 -func (s *Session) Data() map[string]interface{} { +func (s *Session) Map() map[string]interface{} { if len(s.id) > 0 || s.request.Cookie.GetSessionId() != "" { s.init() return s.data.Map() diff --git a/g/os/gfile/gfile.go b/g/os/gfile/gfile.go index 5637be99c..1a97a51dc 100644 --- a/g/os/gfile/gfile.go +++ b/g/os/gfile/gfile.go @@ -440,10 +440,14 @@ func homeWindows() (string, error) { // Available in develop environment. // // 获取入口函数文件所在目录(main包文件目录), -// **仅对源码开发环境有效(即仅对生成该可执行文件的系统下有效)** +// **仅对源码开发环境有效(即仅对生成该可执行文件的系统下有效)**。 +// 注意:该方法被第一次调用时,如果是在异步的goroutine中,该方法可能无法获取到main包路径。 func MainPkgPath() string { path := mainPkgPath.Val() if path != "" { + if path == "-" { + return "" + } return path } for i := 1; i < 10000; i++ { @@ -457,6 +461,8 @@ func MainPkgPath() string { break } } + // 找不到,下次不用再检索了 + mainPkgPath.Set("-") return "" } diff --git a/g/os/gview/gview_doparse.go b/g/os/gview/gview_doparse.go index f6e87a2ef..c1fc12d9e 100644 --- a/g/os/gview/gview_doparse.go +++ b/g/os/gview/gview_doparse.go @@ -31,7 +31,8 @@ var ( // if the template files under changes (recursively). func (view *View) getTemplate(path string, pattern string) (tpl *template.Template, err error) { r := templates.GetOrSetFuncLock(path, func() interface {} { - files, err := gfile.ScanDir(path, pattern, true) + files := ([]string)(nil) + files, err = gfile.ScanDir(path, pattern, true) if err != nil { return nil } @@ -90,7 +91,7 @@ func (view *View) searchFile(file string) (path string, folder string, err error // ParseContent parses given template file // with given template parameters and function map // and returns the parsed string content. -func (view *View) Parse(file string, params map[string]interface{}, funcMap...map[string]interface{}) (parsed string, err error) { +func (view *View) Parse(file string, params...Params) (parsed string, err error) { view.mu.RLock() defer view.mu.RUnlock() path, folder, err := view.searchFile(file) @@ -101,9 +102,6 @@ func (view *View) Parse(file string, params map[string]interface{}, funcMap...ma if err != nil { return "", err } - if len(funcMap) > 0 { - tpl = tpl.Funcs(funcMap[0]) - } tpl, err = tpl.Parse(gfcache.GetContents(path)) if err != nil { return "", err @@ -112,10 +110,16 @@ func (view *View) Parse(file string, params map[string]interface{}, funcMap...ma // of the existing or view.data because both variables are pointers. // It's need to merge the values of the two maps into a new map. vars := (map[string]interface{})(nil) + length := len(view.data) + if len(params) > 0 { + length += len(params[0]) + } + if length > 0 { + vars = make(map[string]interface{}, length) + } if len(view.data) > 0 { if len(params) > 0 { - vars = make(map[string]interface{}, len(view.data) + len(params)) - for k, v := range params { + for k, v := range params[0] { vars[k] = v } for k, v := range view.data { @@ -125,7 +129,9 @@ func (view *View) Parse(file string, params map[string]interface{}, funcMap...ma vars = view.data } } else { - vars = params + if len(params) > 0 { + vars = params[0] + } } buffer := bytes.NewBuffer(nil) if err := tpl.Execute(buffer, vars); err != nil { @@ -137,13 +143,10 @@ func (view *View) Parse(file string, params map[string]interface{}, funcMap...ma // ParseContent parses given template content // with given template parameters and function map // and returns the parsed content in []byte. -func (view *View) ParseContent(content string, params Params, funcMap...map[string]interface{}) (string, error) { +func (view *View) ParseContent(content string, params...Params) (string, error) { view.mu.RLock() defer view.mu.RUnlock() - tpl := template.New("").Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcMap) - if len(funcMap) > 0 { - tpl = tpl.Funcs(funcMap[0]) - } + tpl := template.New("template content").Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcMap) tpl, err := tpl.Parse(content) if err != nil { return "", err @@ -152,10 +155,16 @@ func (view *View) ParseContent(content string, params Params, funcMap...map[stri // of the existing or view.data because both variables are pointers. // It's need to merge the values of the two maps into a new map. vars := (map[string]interface{})(nil) + length := len(view.data) + if len(params) > 0 { + length += len(params[0]) + } + if length > 0 { + vars = make(map[string]interface{}, length) + } if len(view.data) > 0 { if len(params) > 0 { - vars = make(map[string]interface{}, len(view.data) + len(params)) - for k, v := range params { + for k, v := range params[0] { vars[k] = v } for k, v := range view.data { @@ -165,7 +174,9 @@ func (view *View) ParseContent(content string, params Params, funcMap...map[stri vars = view.data } } else { - vars = params + if len(params) > 0 { + vars = params[0] + } } buffer := bytes.NewBuffer(nil) if err := tpl.Execute(buffer, vars); err != nil { diff --git a/g/util/gutil/gutil.go b/g/util/gutil/gutil.go index f64730ed9..ba1eff710 100644 --- a/g/util/gutil/gutil.go +++ b/g/util/gutil/gutil.go @@ -62,7 +62,7 @@ func Export(i...interface{}) string { func PrintBacktrace() { index := 1 buffer := bytes.NewBuffer(nil) - for i := 0; i < 10000; i++ { + for i := 1; i < 10000; i++ { if _, path, line, ok := runtime.Caller(i); ok { buffer.WriteString(fmt.Sprintf(`%d. %s:%d%s`, index, path, line, "\n")) index++ diff --git a/geg/net/ghttp/server/https/https_http.go b/geg/net/ghttp/server/https/https_http.go index 3426ed823..5d5b17321 100644 --- a/geg/net/ghttp/server/https/https_http.go +++ b/geg/net/ghttp/server/https/https_http.go @@ -6,13 +6,12 @@ import ( func main() { s := ghttp.GetServer() - s.EnableAdmin() s.BindHandler("/", func(r *ghttp.Request) { r.Response.Writeln("您可以同时通过HTTP和HTTPS方式看到该内容!") }) s.EnableHTTPS("./server.crt", "./server.key") - s.SetHTTPSPort(8198, 8199) - s.SetPort(8200, 8300) + s.SetHTTPSPort(8100, 8200) + s.SetPort(8300, 8400) s.EnableAdmin() s.Run() } diff --git a/geg/net/ghttp/server/template/build-in/objects/objects.go b/geg/net/ghttp/server/template/build-in/objects/objects.go new file mode 100644 index 000000000..affc834c4 --- /dev/null +++ b/geg/net/ghttp/server/template/build-in/objects/objects.go @@ -0,0 +1,16 @@ +package main + +import ( + "github.com/gogf/gf/g" + "github.com/gogf/gf/g/net/ghttp" +) + +func main() { + s := g.Server() + s.BindHandler("/", func(r *ghttp.Request) { + content := `{{.Request.Get "name"}}` + r.Response.WriteTplContent(content) + }) + s.SetPort(8199) + s.Run() +} diff --git a/geg/net/ghttp/server/template/config.toml b/geg/net/ghttp/server/template/build-in/vars/config.toml similarity index 100% rename from geg/net/ghttp/server/template/config.toml rename to geg/net/ghttp/server/template/build-in/vars/config.toml diff --git a/geg/net/ghttp/server/template/buildin-vars.go b/geg/net/ghttp/server/template/build-in/vars/vars.go similarity index 59% rename from geg/net/ghttp/server/template/buildin-vars.go rename to geg/net/ghttp/server/template/build-in/vars/vars.go index cef7e57b5..5f725a42e 100644 --- a/geg/net/ghttp/server/template/buildin-vars.go +++ b/geg/net/ghttp/server/template/build-in/vars/vars.go @@ -10,8 +10,13 @@ func main() { s.BindHandler("/", func(r *ghttp.Request) { r.Cookie.Set("theme", "default") r.Session.Set("name", "john") - content := `Config:{{.Config.redis.cache}}, Cookie:{{.Cookie.theme}}, Session:{{.Session.name}}` - r.Response.WriteTplContent(content, nil) + content := ` +Get: {{.Get.name}} +Post: {{.Post.name}} +Config: {{.Config.redis}} +Cookie: {{.Cookie.theme}}, +Session: {{.Session.name}}` + r.Response.WriteTplContent(content) }) s.SetPort(8199) s.Run() diff --git a/geg/net/ghttp/server/template/tpl1/tpl1.go b/geg/net/ghttp/server/template/tpl1/tpl1.go index d2d0bb677..4580c70fa 100644 --- a/geg/net/ghttp/server/template/tpl1/tpl1.go +++ b/geg/net/ghttp/server/template/tpl1/tpl1.go @@ -1,6 +1,7 @@ package main import ( + "github.com/gogf/gf/g" "github.com/gogf/gf/g/frame/gmvc" "github.com/gogf/gf/g/net/ghttp" ) @@ -11,7 +12,7 @@ type ControllerIndex struct { func (c *ControllerIndex) Info() { c.View.Assign("title", "Go Frame 第一个网站") - c.View.Assigns(map[string]interface{}{ + c.View.Assigns(g.Map{ "name": "很开心1", "score": 100, }) diff --git a/geg/net/ghttp/server/template/tpl2/main.go b/geg/net/ghttp/server/template/tpl2/main.go index 0b1400b20..c480c9d78 100644 --- a/geg/net/ghttp/server/template/tpl2/main.go +++ b/geg/net/ghttp/server/template/tpl2/main.go @@ -14,9 +14,6 @@ func main() { s.SetAccessLogEnabled(true) s.SetPort(2333) - v := g.View() - v.AddPath("template") - s.BindHandler("/", func(r *ghttp.Request) { content, _ := gins.View().Parse("test.html", nil) r.Response.Write(content) diff --git a/geg/os/gview/layout/layout1/main.go b/geg/os/gview/layout/layout1/main.go index c64276d63..a8fdd87e7 100644 --- a/geg/os/gview/layout/layout1/main.go +++ b/geg/os/gview/layout/layout1/main.go @@ -2,14 +2,20 @@ package main import ( "github.com/gogf/gf/g" - "github.com/gogf/gf/g/net/ghttp" + "github.com/gogf/gf/g/frame/gmvc" ) + +type Controller struct { + gmvc.Controller +} + +func (c *Controller) Test() { + c.View.Display("layout.html") +} func main() { s := g.Server() - s.BindHandler("/", func(r *ghttp.Request) { - r.Response.WriteTpl("layout.html", nil) - }) + s.BindControllerMethod("/", new(Controller), "Test") s.SetPort(8199) s.Run() } diff --git a/geg/other/test.go b/geg/other/test.go index 40d3908e9..5d308c6db 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,52 +1,16 @@ package main import ( - "github.com/gogf/gf/g/container/gset" "fmt" + "github.com/gogf/gf/g/os/gfile" + "time" ) func main() { - // 创建一个非并发安全的集合对象 - s := gset.New(true) - - // 添加数据项 - s.Add(1) - - // 批量添加数据项 - s.Add([]interface{}{1, 2, 3}...) - - // 集合数据项大小 - fmt.Println(s.Size()) - - // 集合中是否存在指定数据项 - fmt.Println(s.Contains(2)) - - // 返回数据项slice - fmt.Println(s.Slice()) - - // 删除数据项 - s.Remove(3) - - // 遍历数据项 - s.Iterator(func(v interface{}) bool { - fmt.Println("Iterator:", v) - return true - }) - - // 将集合转换为字符串 - fmt.Println(s.String()) - - // 并发安全写锁操作 - s.LockFunc(func(m map[interface{}]struct{}) { - m[4] = struct{}{} - }) - - // 并发安全读锁操作 - s.RLockFunc(func(m map[interface{}]struct{}) { - fmt.Println(m) - }) - - // 清空集合 - s.Clear() - fmt.Println(s.Size()) + go func() { + go func() { + fmt.Println("main:", gfile.MainPkgPath()) + }() + }() + time.Sleep(time.Second) } \ No newline at end of file diff --git a/version.go b/version.go index e4aa2861b..322a1ca3a 100644 --- a/version.go +++ b/version.go @@ -1,4 +1,4 @@ package gf -const VERSION = "v1.6.4" +const VERSION = "v1.6.5" const AUTHORS = "john"