diff --git a/README.MD b/README.MD index ab18f553f..aa3e5a7f8 100644 --- a/README.MD +++ b/README.MD @@ -40,6 +40,7 @@ golang version >= 1.10 # Quick Start +## Hello World ```go package main @@ -56,8 +57,231 @@ func main() { s.Run() } ``` +## Rich Router +```go +package main -[View More..](https://goframe.org/start/index) +import ( + "github.com/gogf/gf/g/net/ghttp" + "github.com/gogf/gf/g" +) + +func main() { + s := g.Server() + s.BindHandler("/{class}-{course}/:name/*act", func(r *ghttp.Request) { + r.Response.Writeln(r.Get("class")) + r.Response.Writeln(r.Get("course")) + r.Response.Writeln(r.Get("name")) + r.Response.Writeln(r.Get("act")) + }) + s.SetPort(8199) + s.Run() +} +``` +## Group Routers +```go +package main + +import ( + "github.com/gogf/gf/g" + "github.com/gogf/gf/g/net/ghttp" +) + +type Object struct {} + +func (o *Object) Show(r *ghttp.Request) { + r.Response.Writeln("Object Show") +} + +func (o *Object) Delete(r *ghttp.Request) { + r.Response.Writeln("Object REST Delete") +} + +func Handler(r *ghttp.Request) { + r.Response.Writeln("Handler") +} + +func HookHandler(r *ghttp.Request) { + r.Response.Writeln("Hook Handler") +} + +func main() { + s := g.Server() + obj := new(Object) + group := s.Group("/api") + group.ALL ("*", HookHandler, ghttp.HOOK_BEFORE_SERVE) + group.ALL ("/handler", Handler) + group.ALL ("/obj", obj) + group.GET ("/obj/showit", obj, "Show") + group.REST("/obj/rest", obj) + s.SetPort(8199) + s.Run() +} +``` +or +```go +func main() { + s := g.Server() + obj := new(Object) + s.Group("/api").Bind([]ghttp.GroupItem{ + {"ALL", "*", HookHandler, ghttp.HOOK_BEFORE_SERVE}, + {"ALL", "/handler", Handler}, + {"ALL", "/obj", obj}, + {"GET", "/obj/showit", obj, "Show"}, + {"REST", "/obj/rest", obj}, + }) + s.SetPort(8199) + s.Run() +} +``` +## Multi ports & domains +```go +package main + +import ( + "github.com/gogf/gf/g" + "github.com/gogf/gf/g/net/ghttp" +) + +func Hello1(r *ghttp.Request) { + r.Response.Write("127.0.0.1: Hello1!") +} + +func Hello2(r *ghttp.Request) { + r.Response.Write("localhost: Hello2!") +} + +func main() { + s := g.Server() + s.Domain("127.0.0.1").BindHandler("/", Hello1) + s.Domain("localhost").BindHandler("/", Hello2) + s.SetPort(8100, 8200, 8300) + s.Run() +} +``` +## Template Engine +```go +package main + +import ( + "github.com/gogf/gf/g" + "github.com/gogf/gf/g/net/ghttp" +) + +func main() { + s := g.Server() + s.BindHandler("/template", func(r *ghttp.Request) { + r.Response.WriteTpl("index.tpl", g.Map{ + "id": 123, + "name": "john", + }) + }) + s.SetPort(8199) + s.Run() +} +``` +## File Uploading +```go +func Upload(r *ghttp.Request) { + if f, h, e := r.FormFile("upload-file"); e == nil { + defer f.Close() + name := gfile.Basename(h.Filename) + buffer := make([]byte, h.Size) + f.Read(buffer) + gfile.PutBinContents("/tmp/" + name, buffer) + r.Response.Write(name + " uploaded successly") + } else { + r.Response.Write(e.Error()) + } +} +``` + +## ORM Operations + +### 1. Retrieving instance +```go +db := g.DB() +db := g.DB("user-center") +``` +### 2. Chaining Operations + +`Where + string` +```go +// SELECT * FROM user WHERE uid>1 LIMIT 0,10 +r, err := db.Table("user").Where("uid > ?", 1).Limit(0, 10).Select() + +// SELECT uid,name FROM user WHERE uid>1 LIMIT 0,10 +r, err := db.Table("user").Fileds("uid,name").Where("uid > ?", 1).Limit(0, 10).Select() + +// SELECT * FROM user WHERE uid=1 +r, err := db.Table("user").Where("u.uid=1",).One() +r, err := db.Table("user").Where("u.uid", 1).One() +r, err := db.Table("user").Where("u.uid=?", 1).One() +// SELECT * FROM user WHERE (uid=1) AND (name='john') +r, err := db.Table("user").Where("uid", 1).Where("name", "john").One() +r, err := db.Table("user").Where("uid=?", 1).And("name=?", "john").One() +// SELECT * FROM user WHERE (uid=1) OR (name='john') +r, err := db.Table("user").Where("uid=?", 1).Or("name=?", "john").One() +``` +`Where + map` +```go +// SELECT * FROM user WHERE uid=1 AND name='john' +r, err := db.Table("user").Where(g.Map{"uid" : 1, "name" : "john"}).One() +// SELECT * FROM user WHERE uid=1 AND age>18 +r, err := db.Table("user").Where(g.Map{"uid" : 1, "age>" : 18}).One() +``` +`Where + struct/*struct` +```go +type User struct { + Id int `json:"uid"` + UserName string `gconv:"name"` +} +// SELECT * FROM user WHERE uid =1 AND name='john' +r, err := db.Table("user").Where(User{ Id : 1, UserName : "john"}).One() +// SELECT * FROM user WHERE uid =1 +r, err := db.Table("user").Where(&User{ Id : 1}).One() +``` +### 3. Update & Delete +```go +// UPDATE user SET name='john guo' WHERE name='john' +r, err := db.Table("user").Data(gdb.Map{"name" : "john guo"}).Where("name=?", "john").Update() +r, err := db.Table("user").Data("name='john guo'").Where("name=?", "john").Update() +// UPDATE user SET status=1 ORDER BY login_time asc LIMIT 10 +r, err := db.Table("user").Data("status", 1).OrderBy("login_time asc").Limit(10).Update + +// DELETE FROM user WHERE uid=10 +r, err := db.Table("user").Where("uid=?", 10).Delete() +// DELETE FROM user ORDER BY login_time asc LIMIT 10 +r, err := db.Table("user").OrderBy("login_time asc").Limit(10).Delete() +``` +### 4. Insert & Replace & Save +```go +r, err := db.Table("user").Data(g.Map{"name": "john"}).Insert() +r, err := db.Table("user").Data(g.Map{"uid": 10000, "name": "john"}).Replace() +r, err := db.Table("user").Data(g.Map{"uid": 10001, "name": "john"}).Save() +``` +### 5. Transaction +```go +if tx, err := db.Begin(); err == nil { + r, err := tx.Save("user", g.Map{ + "uid" : 1, + "name" : "john", + }) + tx.Commit() +} +``` +### 6. Error Handling +```go +func GetOrderInfo(id int) (order *Order, err error) { + err = g.DB().Table("order").Where("id", id).Struct(&order) + if err != nil && err == sql.ErrNoRows { + err = nil + } + return +} +``` + +[More Features...](https://goframe.org/start/index) # License diff --git a/g/container/gvar/gvar.go b/g/container/gvar/gvar.go index 05b3098e8..bbf3543d9 100644 --- a/g/container/gvar/gvar.go +++ b/g/container/gvar/gvar.go @@ -58,33 +58,6 @@ func (v *Var) Interface() interface{} { return v.Val() } -// Time converts and returns as time.Time. -// The parameter specifies the format of the time string using gtime, -// eg: Y-m-d H:i:s. -func (v *Var) Time(format ...string) time.Time { - return gconv.Time(v.Val(), format...) -} - -// Duration converts and returns as time.Duration. -// If value of is string, then it uses time.ParseDuration for conversion. -func (v *Var) Duration() time.Duration { - return gconv.Duration(v.Val()) -} - -// GTime converts and returns as *gtime.Time. -// The parameter specifies the format of the time string using gtime, -// eg: Y-m-d H:i:s. -func (v *Var) GTime(format ...string) *gtime.Time { - return gconv.GTime(v.Val(), format...) -} - -// Struct maps value of to . -// The parameter should be a pointer to a struct instance. -// The parameter is used to specify the key-to-attribute mapping rules. -func (v *Var) Struct(pointer interface{}, mapping ...map[string]string) error { - return gconv.Struct(v.Val(), pointer, mapping...) -} - // IsNil checks whether is nil. func (v *Var) IsNil() bool { return v.Val() == nil @@ -184,3 +157,57 @@ func (v *Var) Strings() []string { func (v *Var) Interfaces() []interface{} { return gconv.Interfaces(v.Val()) } + +// Time converts and returns as time.Time. +// The parameter specifies the format of the time string using gtime, +// eg: Y-m-d H:i:s. +func (v *Var) Time(format ...string) time.Time { + return gconv.Time(v.Val(), format...) +} + +// Duration converts and returns as time.Duration. +// If value of is string, then it uses time.ParseDuration for conversion. +func (v *Var) Duration() time.Duration { + return gconv.Duration(v.Val()) +} + +// GTime converts and returns as *gtime.Time. +// The parameter specifies the format of the time string using gtime, +// eg: Y-m-d H:i:s. +func (v *Var) GTime(format ...string) *gtime.Time { + return gconv.GTime(v.Val(), format...) +} + +// Map converts to map[string]interface{}. +func (v *Var) Map(tags ...string) map[string]interface{} { + return gconv.Map(v.Val(), tags...) +} + +// MapDeep converts to map[string]interface{} recursively. +func (v *Var) MapDeep(tags ...string) map[string]interface{} { + return gconv.MapDeep(v.Val(), tags...) +} + +// Struct maps value of to . +// The parameter should be a pointer to a struct instance. +// The parameter is used to specify the key-to-attribute mapping rules. +func (v *Var) Struct(pointer interface{}, mapping ...map[string]string) error { + return gconv.Struct(v.Val(), pointer, mapping...) +} + +// Struct maps value of to recursively. +// The parameter should be a pointer to a struct instance. +// The parameter is used to specify the key-to-attribute mapping rules. +func (v *Var) StructDeep(pointer interface{}, mapping ...map[string]string) error { + return gconv.StructDeep(v.Val(), pointer, mapping...) +} + +// Structs converts to given struct slice. +func (v *Var) Structs(pointer interface{}, mapping ...map[string]string) (err error) { + return gconv.Structs(v.Val(), pointer, mapping...) +} + +// StructsDeep converts to given struct slice recursively. +func (v *Var) StructsDeep(pointer interface{}, mapping ...map[string]string) (err error) { + return gconv.StructsDeep(v.Val(), pointer, mapping...) +} diff --git a/g/database/gdb/gdb_unit_model_test.go b/g/database/gdb/gdb_unit_model_test.go index 8b5431fd5..2971ad3bd 100644 --- a/g/database/gdb/gdb_unit_model_test.go +++ b/g/database/gdb/gdb_unit_model_test.go @@ -673,6 +673,21 @@ func TestModel_Where(t *testing.T) { gtest.Assert(err, nil) gtest.Assert(result["id"].Int(), 3) }) + // slice + gtest.Case(t, func() { + result, err := db.Table("user").Where("id=? AND nickname=?", g.Slice{3, "T3"}...).One() + if err != nil { + gtest.Fatal(err) + } + gtest.Assert(result["id"].Int(), 3) + }) + gtest.Case(t, func() { + result, err := db.Table("user").Where("passport like ? and nickname like ?", g.Slice{"t3", "T3"}...).One() + if err != nil { + gtest.Fatal(err) + } + gtest.Assert(result["id"].Int(), 3) + }) // map gtest.Case(t, func() { result, err := db.Table("user").Where(g.Map{"id": 3, "nickname": "T3"}).One() diff --git a/g/encoding/gbase64/gbase64.go b/g/encoding/gbase64/gbase64.go index e19733002..0a01680ff 100644 --- a/g/encoding/gbase64/gbase64.go +++ b/g/encoding/gbase64/gbase64.go @@ -22,10 +22,7 @@ func Encode(src []byte) []byte { func Decode(dst []byte) ([]byte, error) { src := make([]byte, base64.StdEncoding.DecodedLen(len(dst))) n, err := base64.StdEncoding.Decode(src, dst) - if err != nil { - return nil, err - } - return src[:n], nil + return src[:n], err } // EncodeString encodes bytes with BASE64 algorithm. diff --git a/g/encoding/gjson/gjson_api.go b/g/encoding/gjson/gjson_api.go index b83316d30..a03a50f60 100644 --- a/g/encoding/gjson/gjson_api.go +++ b/g/encoding/gjson/gjson_api.go @@ -266,11 +266,32 @@ func (j *Json) GetToVar(pattern string, pointer interface{}) error { return nil } -// GetToStruct gets the value by specified , -// and converts it to specified object . -// The should be the pointer to an object. -func (j *Json) GetToStruct(pattern string, pointer interface{}) error { - return gconv.Struct(j.Get(pattern), pointer) +// GetStruct gets the value by specified , +// and converts it to specified object . +// The should be the pointer to an object. +func (j *Json) GetStruct(pattern string, pointer interface{}, mapping ...map[string]string) error { + return gconv.Struct(j.Get(pattern), pointer, mapping...) +} + +// GetStructDeep does GetStruct recursively. +func (j *Json) GetStructDeep(pattern string, pointer interface{}, mapping ...map[string]string) error { + return gconv.StructDeep(j.Get(pattern), pointer, mapping...) +} + +// GetStructs converts any slice to given struct slice. +func (j *Json) GetStructs(pattern string, pointer interface{}, mapping ...map[string]string) error { + return gconv.Structs(j.Get(pattern), pointer, mapping...) +} + +// GetStructsDeep converts any slice to given struct slice recursively. +func (j *Json) GetStructsDeep(pattern string, pointer interface{}, mapping ...map[string]string) error { + return gconv.StructsDeep(j.Get(pattern), pointer, mapping...) +} + +// GetToStruct is alias of GetStruct. +// Deprecated. +func (j *Json) GetToStruct(pattern string, pointer interface{}, mapping ...map[string]string) error { + return j.GetStruct(pattern, pointer, mapping...) } // ToMap converts current Json object to map[string]interface{}. @@ -290,7 +311,7 @@ func (j *Json) ToArray() []interface{} { } // ToStruct converts current Json object to specified object. -// The should be a pointer type. +// The should be a pointer type. func (j *Json) ToStruct(pointer interface{}) error { j.mu.RLock() defer j.mu.RUnlock() diff --git a/g/encoding/gparser/gparser_api.go b/g/encoding/gparser/gparser_api.go index 659b2c7dc..2b5261a09 100644 --- a/g/encoding/gparser/gparser_api.go +++ b/g/encoding/gparser/gparser_api.go @@ -145,11 +145,32 @@ func (p *Parser) GetToVar(pattern string, pointer interface{}) error { return p.json.GetToVar(pattern, pointer) } -// GetToStruct gets the value by specified , +// GetStruct gets the value by specified , // and converts it to specified object . -// The should be the pointer to a struct. -func (p *Parser) GetToStruct(pattern string, pointer interface{}) error { - return p.json.GetToStruct(pattern, pointer) +// The should be the pointer to an object. +func (p *Parser) GetStruct(pattern string, pointer interface{}, mapping ...map[string]string) error { + return p.json.GetStruct(pattern, pointer, mapping...) +} + +// GetStructDeep does GetStruct recursively. +func (p *Parser) GetStructDeep(pattern string, pointer interface{}, mapping ...map[string]string) error { + return p.json.GetStructDeep(pattern, pointer, mapping...) +} + +// GetStructs converts any slice to given struct slice. +func (p *Parser) GetStructs(pattern string, pointer interface{}, mapping ...map[string]string) error { + return p.json.GetStructs(pattern, pointer, mapping...) +} + +// GetStructsDeep converts any slice to given struct slice recursively. +func (p *Parser) GetStructsDeep(pattern string, pointer interface{}, mapping ...map[string]string) error { + return p.json.GetStructsDeep(pattern, pointer, mapping...) +} + +// GetToStruct is alias of GetStruct. +// Deprecated. +func (p *Parser) GetToStruct(pattern string, pointer interface{}, mapping ...map[string]string) error { + return p.json.GetStruct(pattern, pointer, mapping...) } // Set sets value with specified . diff --git a/g/net/ghttp/ghttp_request_post.go b/g/net/ghttp/ghttp_request_post.go index 6a594fd1b..193544256 100644 --- a/g/net/ghttp/ghttp_request_post.go +++ b/g/net/ghttp/ghttp_request_post.go @@ -154,5 +154,5 @@ func (r *Request) GetPostToStruct(pointer interface{}, mapping ...map[string]str for k, v := range r.GetPostMap() { params[k] = v } - return gconv.Struct(params, pointer, tagMap) + return gconv.StructDeep(params, pointer, tagMap) } diff --git a/g/os/gcfg/gcfg.go b/g/os/gcfg/gcfg.go index 1badfa033..adb3fa570 100644 --- a/g/os/gcfg/gcfg.go +++ b/g/os/gcfg/gcfg.go @@ -489,14 +489,41 @@ func (c *Config) GetGTime(pattern string, format ...string) *gtime.Time { return nil } -func (c *Config) GetToStruct(pattern string, pointer interface{}, def ...interface{}) error { +func (c *Config) GetStruct(pattern string, pointer interface{}, mapping ...map[string]string) error { if j := c.getJson(); j != nil { - return j.GetToStruct(pattern, pointer) + return j.GetStruct(pattern, pointer, mapping...) } return errors.New("config file not found") } -// Deprecated. See Clear. +func (c *Config) GetStructDeep(pattern string, pointer interface{}, mapping ...map[string]string) error { + if j := c.getJson(); j != nil { + return j.GetStructDeep(pattern, pointer, mapping...) + } + return errors.New("config file not found") +} + +func (c *Config) GetStructs(pattern string, pointer interface{}, mapping ...map[string]string) error { + if j := c.getJson(); j != nil { + return j.GetStructs(pattern, pointer, mapping...) + } + return errors.New("config file not found") +} + +func (c *Config) GetStructsDeep(pattern string, pointer interface{}, mapping ...map[string]string) error { + if j := c.getJson(); j != nil { + return j.GetStructsDeep(pattern, pointer, mapping...) + } + return errors.New("config file not found") +} + +// Deprecated. +func (c *Config) GetToStruct(pattern string, pointer interface{}) error { + return c.GetStruct(pattern, pointer) +} + +// Reload is alias of Clear. +// Deprecated. func (c *Config) Reload() { c.jsons.Clear() } diff --git a/g/os/gfile/gfile.go b/g/os/gfile/gfile.go index 81db327e2..717ffae7e 100644 --- a/g/os/gfile/gfile.go +++ b/g/os/gfile/gfile.go @@ -11,11 +11,8 @@ import ( "bytes" "errors" "fmt" - "github.com/gogf/gf/g/container/gtype" - "github.com/gogf/gf/g/text/gregex" - "github.com/gogf/gf/g/text/gstr" - "github.com/gogf/gf/g/util/gconv" "io" + "io/ioutil" "os" "os/exec" "os/user" @@ -24,6 +21,11 @@ import ( "sort" "strings" "time" + + "github.com/gogf/gf/g/container/gtype" + "github.com/gogf/gf/g/text/gregex" + "github.com/gogf/gf/g/text/gstr" + "github.com/gogf/gf/g/util/gconv" ) const ( @@ -142,29 +144,109 @@ func Rename(src string, dst string) error { return Move(src, dst) } -// Copy file from to . +// Copy file/directory from to . // -// @TODO directory copy support. +// If is file, it calls CopyFile to implements copy feature, +// or else it calls CopyDir. func Copy(src string, dst string) error { - srcFile, err := Open(src) + if IsFile(src) { + return CopyFile(src, dst) + } + return CopyDir(src, dst) +} + +// CopyFile copies the contents of the file named src to the file named +// by dst. The file will be created if it does not already exist. If the +// destination file exists, all it's contents will be replaced by the contents +// of the source file. The file mode will be copied from the source and +// the copied data is synced/flushed to stable storage. +// Thanks: https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04 +func CopyFile(src, dst string) (err error) { + in, err := os.Open(src) + if err != nil { + return + } + defer func() { + if e := in.Close(); e != nil { + err = e + } + }() + out, err := os.Create(dst) + if err != nil { + return + } + defer func() { + if e := out.Close(); e != nil { + err = e + } + }() + _, err = io.Copy(out, in) + if err != nil { + return + } + err = out.Sync() + if err != nil { + return + } + si, err := os.Stat(src) + if err != nil { + return + } + err = os.Chmod(dst, si.Mode()) + if err != nil { + return + } + return +} + +// CopyDir recursively copies a directory tree, attempting to preserve permissions. +// Source directory must exist, destination directory must *not* exist. +// Symlinks are ignored and skipped. +func CopyDir(src string, dst string) (err error) { + src = filepath.Clean(src) + dst = filepath.Clean(dst) + si, err := os.Stat(src) if err != nil { return err } - defer srcFile.Close() - dstFile, err := Create(dst) - if err != nil { - return err + if !si.IsDir() { + return fmt.Errorf("source is not a directory") } - defer dstFile.Close() - _, err = io.Copy(dstFile, srcFile) - if err != nil { - return err + _, err = os.Stat(dst) + if err != nil && !os.IsNotExist(err) { + return } - err = dstFile.Sync() - if err != nil { - return err + if err == nil { + return fmt.Errorf("destination already exists") } - return nil + err = os.MkdirAll(dst, si.Mode()) + if err != nil { + return + } + entries, err := ioutil.ReadDir(src) + if err != nil { + return + } + for _, entry := range entries { + srcPath := filepath.Join(src, entry.Name()) + dstPath := filepath.Join(dst, entry.Name()) + if entry.IsDir() { + err = CopyDir(srcPath, dstPath) + if err != nil { + return + } + } else { + // Skip symlinks. + if entry.Mode()&os.ModeSymlink != 0 { + continue + } + err = CopyFile(srcPath, dstPath) + if err != nil { + return + } + } + } + return } // DirNames returns sub-file names of given directory . diff --git a/g/os/gfile/gfile_z_test.go b/g/os/gfile/gfile_z_test.go index b7d438434..44b8008ed 100644 --- a/g/os/gfile/gfile_z_test.go +++ b/g/os/gfile/gfile_z_test.go @@ -1,12 +1,13 @@ package gfile_test import ( - "github.com/gogf/gf/g/os/gfile" - "github.com/gogf/gf/g/test/gtest" "os" "path/filepath" "strings" "testing" + + "github.com/gogf/gf/g/os/gfile" + "github.com/gogf/gf/g/test/gtest" ) func TestIsDir(t *testing.T) { @@ -677,3 +678,71 @@ func TestMainPkgPath(t *testing.T) { gtest.Assert(reads, "") }) } + +func TestCopyFile(t *testing.T) { + gtest.Case(t, func() { + var ( + paths string = "/testfile_copyfile1.txt" + topath string = "/testfile_copyfile2.txt" + ) + + createTestFile(paths, "") + defer delTestFiles(paths) + + gtest.Assert(gfile.CopyFile(testpath()+paths, testpath()+topath), nil) + defer delTestFiles(topath) + + gtest.Assert(gfile.IsFile(testpath()+topath), true) + gtest.AssertNE(gfile.CopyFile("", ""), nil) + }) +} + +func TestCopyDir(t *testing.T) { + gtest.Case(t, func() { + var ( + dirpath1 string = "/testcopydir1" + dirpath2 string = "/testcopydir2" + ) + + havelist1 := []string{ + "t1.txt", + "t2.txt", + } + + createDir(dirpath1) + for _, v := range havelist1 { + createTestFile(dirpath1+"/"+v, "") + } + defer delTestFiles(dirpath1) + + yfolder := testpath() + dirpath1 + tofolder := testpath() + dirpath2 + + if gfile.IsDir(tofolder) { + gtest.Assert(gfile.Remove(tofolder), nil) + gtest.Assert(gfile.Remove(""), nil) + } + + gtest.Assert(gfile.CopyDir(yfolder, tofolder), nil) + defer delTestFiles(tofolder) + + // 检查复制后的旧文件夹是否真实存在 + gtest.Assert(gfile.IsDir(yfolder), true) + + // 检查复制后的旧文件夹中的文件是否真实存在 + for _, v := range havelist1 { + gtest.Assert(gfile.IsFile(yfolder+"/"+v), true) + } + + // 检查复制后的新文件夹是否真实存在 + gtest.Assert(gfile.IsDir(tofolder), true) + + // 检查复制后的新文件夹中的文件是否真实存在 + for _, v := range havelist1 { + gtest.Assert(gfile.IsFile(tofolder+"/"+v), true) + } + + gtest.Assert(gfile.Remove(tofolder), nil) + gtest.Assert(gfile.Remove(""), nil) + }) +} diff --git a/g/os/gfsnotify/gfsnotify_watcher_loop.go b/g/os/gfsnotify/gfsnotify_watcher_loop.go index 0fe2215a3..1199fb65f 100644 --- a/g/os/gfsnotify/gfsnotify_watcher_loop.go +++ b/g/os/gfsnotify/gfsnotify_watcher_loop.go @@ -7,8 +7,6 @@ package gfsnotify import ( - "fmt" - "github.com/gogf/gf/g/container/glist" ) @@ -23,7 +21,7 @@ func (w *Watcher) startWatchLoop() { // 监听事件 case ev := <-w.watcher.Events: - fmt.Println("ev:", ev.String()) + //fmt.Println("ev:", ev.String()) w.cache.SetIfNotExist(ev.String(), func() interface{} { w.events.Push(&Event{ event: ev, diff --git a/g/util/gconv/gconv_slice.go b/g/util/gconv/gconv_slice.go index d9f57d500..2b7178bae 100644 --- a/g/util/gconv/gconv_slice.go +++ b/g/util/gconv/gconv_slice.go @@ -14,6 +14,46 @@ import ( "github.com/gogf/gf/g/text/gstr" ) +// SliceInt is alias of Ints. +func SliceInt(i interface{}) []int { + return Ints(i) +} + +// SliceStr is alias of Strings. +func SliceStr(i interface{}) []string { + return Strings(i) +} + +// SliceAny is alias of Interfaces. +func SliceAny(i interface{}) []interface{} { + return Interfaces(i) +} + +// SliceFloat is alias of Floats. +func SliceFloat(i interface{}) []float64 { + return Floats(i) +} + +// SliceMap is alias of Maps. +func SliceMap(i interface{}) []map[string]interface{} { + return Maps(i) +} + +// SliceMapDeep is alias of MapsDeep. +func SliceMapDeep(i interface{}) []map[string]interface{} { + return MapsDeep(i) +} + +// SliceStruct is alias of Structs. +func SliceStruct(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) { + return Structs(params, pointer, mapping...) +} + +// SliceStructDeep is alias of StructsDeep. +func SliceStructDeep(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) { + return StructsDeep(params, pointer, mapping...) +} + // Ints converts to []int. func Ints(i interface{}) []int { if i == nil { @@ -350,6 +390,26 @@ func Maps(i interface{}) []map[string]interface{} { } } +// MapsDeep converts to []map[string]interface{} recursively. +func MapsDeep(i interface{}) []map[string]interface{} { + if i == nil { + return nil + } + if r, ok := i.([]map[string]interface{}); ok { + return r + } else { + array := Interfaces(i) + if len(array) == 0 { + return nil + } + list := make([]map[string]interface{}, len(array)) + for k, v := range array { + list[k] = MapDeep(v) + } + return list + } +} + // Structs converts any slice to given struct slice. func Structs(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) { return doStructs(params, pointer, false, mapping...) diff --git a/geg/other/test.go b/geg/other/test.go index 94f49578c..381a581b9 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,27 +1,19 @@ package main import ( - "github.com/gogf/gf/g" - "github.com/gogf/gf/g/util/gvalid" + "encoding/base64" + "fmt" + "github.com/gogf/gf/g/encoding/gbase64" ) func main() { - type Pass struct { - Pass1 string `valid:"password1@required|same:password2#请输入您的密码|您两次输入的密码不一致"` - Pass2 string `valid:"password2@required|same:password1#请再次输入您的密码|您两次输入的密码不一致"` - } - type User struct { - Id int - Name string `valid:"name@required#请输入您的姓名"` - Pass Pass - } - user := &User{ - Name: "john", - Pass: Pass{ - Pass1: "1", - Pass2: "2", - }, - } - err := gvalid.CheckStruct(user, nil) - g.Dump(err.Maps()) + data := "HwHsGhXMaGc===" + datab, err := gbase64.Decode([]byte(data)) + fmt.Println(err) + fmt.Println(datab) + fmt.Println(string(datab)) + + s, e := base64.StdEncoding.DecodeString(data) + fmt.Println(e) + fmt.Println(string(s)) } diff --git a/go.mod b/go.mod index fd3232e72..28729e4f6 100644 --- a/go.mod +++ b/go.mod @@ -1 +1,2 @@ -module github.com/gogf/gf \ No newline at end of file +module github.com/gogf/gf +