mirror of
https://gitee.com/johng/gf
synced 2026-06-23 16:34:17 +08:00
Merge branch 'master' of https://gitee.com/johng/gf into develop
This commit is contained in:
@ -36,10 +36,10 @@ golang版本 >= 1.9.2
|
||||
1. 提供了对基本数据类型的并发安全封装,提供了常用的数据结构容器;
|
||||
1. 支持Go变量/Json/Xml/Yml/Toml任意数据格式之间的相互转换及创建;
|
||||
1. 强大的数据库ORM,支持应用层级的集群管理、读写分离、负载均衡,查询缓存、方法及链式ORM操作;
|
||||
1. 更多特点请查阅框架[手册](http://gf.johng.cn)和[源码](https://godoc.org/github.com/johng-cn/gf);
|
||||
1. 更多特点请查阅框架[手册](https://gfer.me)和[源码](https://godoc.org/github.com/johng-cn/gf);
|
||||
|
||||
# 文档
|
||||
GoFrame开发文档:[http://gf.johng.cn](http://gf.johng.cn)
|
||||
GoFrame开发文档:[gfer.me](https://gfer.me)
|
||||
|
||||
|
||||
# 使用
|
||||
@ -178,4 +178,4 @@ if tx, err := db.Begin(); err == nil {
|
||||
...
|
||||
|
||||
|
||||
更多特性及示例请查看官方开发文档:[gf.johng.cn](http://gf.johng.cn)
|
||||
更多特性及示例请查看官方开发文档:[gfer.me](https://gfer.me)
|
||||
|
||||
1
TODO
1
TODO
@ -45,6 +45,7 @@ gform参考 https://gohouse.github.io/gorose/dist/index.html 进行改进
|
||||
完善gform配置管理说明,g.DB/Database和gdb.New的区别;
|
||||
|
||||
|
||||
|
||||
DONE:
|
||||
1. gconv完善针对不同类型的判断,例如:尽量减少sprintf("%v", xxx)来执行string类型的转换;
|
||||
2. ghttp.Server请求执行中增加服务退出的方法,不再执行后续操作;
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"gitee.com/johng/gf/g/os/gcfg"
|
||||
"gitee.com/johng/gf/g/os/gcmd"
|
||||
"gitee.com/johng/gf/g/os/genv"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"gitee.com/johng/gf/g/os/gview"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g/container/gmap"
|
||||
@ -125,7 +126,7 @@ func Database(name...string) *gdb.Db {
|
||||
db := instances.GetOrSetFuncLock(key, func() interface{} {
|
||||
m := config.GetMap("database")
|
||||
if m == nil {
|
||||
panic(fmt.Sprintf(`incomplete configuration for database: "database" node not found in config file "%s"`, config.GetFilePath()))
|
||||
glog.Errorfln(`incomplete configuration for database: "database" node not found in config file "%s"`, config.GetFilePath())
|
||||
}
|
||||
for group, v := range m {
|
||||
cg := gdb.ConfigGroup{}
|
||||
@ -160,6 +161,9 @@ func Database(name...string) *gdb.Db {
|
||||
if value, ok := nodem["priority"]; ok {
|
||||
node.Priority = gconv.Int(value)
|
||||
}
|
||||
if value, ok := nodem["linkinfo"]; ok {
|
||||
node.Linkinfo = gconv.String(value)
|
||||
}
|
||||
if value, ok := nodem["max-idle"]; ok {
|
||||
node.MaxIdleConnCount = gconv.Int(value)
|
||||
}
|
||||
@ -181,7 +185,7 @@ func Database(name...string) *gdb.Db {
|
||||
if db, err := gdb.New(name...); err == nil {
|
||||
return db
|
||||
} else {
|
||||
panic(err)
|
||||
glog.Error(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@ -213,13 +217,13 @@ func Redis(name...string) *gredis.Redis {
|
||||
Pass : array[4],
|
||||
})
|
||||
} else {
|
||||
panic(fmt.Sprintf(`invalid redis node configuration: "%s"`, line))
|
||||
glog.Errorfln(`invalid redis node configuration: "%s"`, line)
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Sprintf(`configuration for redis not found for group "%s"`, group))
|
||||
glog.Errorfln(`configuration for redis not found for group "%s"`, group)
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Sprintf(`incomplete configuration for redis: "redis" node not found in config file "%s"`, config.GetFilePath()))
|
||||
glog.Errorfln(`incomplete configuration for redis: "redis" node not found in config file "%s"`, config.GetFilePath())
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
10
g/g_func.go
10
g/g_func.go
@ -33,16 +33,6 @@ func Wait() {
|
||||
ghttp.Wait()
|
||||
}
|
||||
|
||||
// 是否显示调试信息
|
||||
func SetDebug(debug bool) {
|
||||
glog.SetDebug(debug)
|
||||
}
|
||||
|
||||
// 设置日志的显示等级
|
||||
func SetLogLevel(level int) {
|
||||
glog.SetLevel(level)
|
||||
}
|
||||
|
||||
// 打印变量
|
||||
func Dump(i...interface{}) {
|
||||
gutil.Dump(i...)
|
||||
|
||||
@ -6,3 +6,19 @@
|
||||
|
||||
package g
|
||||
|
||||
import "gitee.com/johng/gf/g/os/glog"
|
||||
|
||||
// 是否显示调试信息
|
||||
func SetDebug(debug bool) {
|
||||
glog.SetDebug(debug)
|
||||
}
|
||||
|
||||
// 设置日志的显示等级
|
||||
func SetLogLevel(level int) {
|
||||
glog.SetLevel(level)
|
||||
}
|
||||
|
||||
// 获取设置的日志显示等级
|
||||
func GetLogLevel() int {
|
||||
return glog.GetLevel()
|
||||
}
|
||||
@ -213,9 +213,14 @@ func (s *Server) Start() error {
|
||||
// 如果设置了静态文件目录,那么优先按照静态文件目录进行检索,其次是当前可执行文件工作目录;
|
||||
// 并且如果是开发环境,默认也会添加main包的源码目录路径做为二级检索。
|
||||
if s.config.ServerRoot != "" {
|
||||
s.paths.Set(s.config.ServerRoot)
|
||||
if rp, err := s.paths.Set(s.config.ServerRoot); err != nil {
|
||||
glog.Error("ghttp.SetServerRoot failed:", err.Error())
|
||||
return err
|
||||
} else {
|
||||
glog.Debug("ghttp.SetServerRoot:", rp)
|
||||
}
|
||||
}
|
||||
s.paths.Add(gfile.SelfDir())
|
||||
s.AddSearchPath(gfile.SelfDir())
|
||||
if p := gfile.MainPkgPath(); p != "" && gfile.Exists(p) {
|
||||
s.paths.Add(p)
|
||||
}
|
||||
@ -271,7 +276,7 @@ func (s *Server) Start() error {
|
||||
|
||||
// 打印展示路由表
|
||||
func (s *Server) DumpRoutesMap() {
|
||||
if s.config.DumpRouteMap {
|
||||
if s.config.DumpRouteMap && len(s.routesMap) > 0 {
|
||||
// (等待一定时间后)当所有框架初始化信息打印完毕之后才打印路由表信息
|
||||
gtime.SetTimeout(50*time.Millisecond, func() {
|
||||
glog.Header(false).Println(fmt.Sprintf("\n%s\n", s.GetRouteMap()))
|
||||
|
||||
@ -303,7 +303,13 @@ func (s *Server) SetDumpRouteMap(enabled bool) {
|
||||
|
||||
// 添加静态文件搜索目录,必须给定目录的绝对路径
|
||||
func (s *Server) AddSearchPath(path string) error {
|
||||
return s.paths.Add(path)
|
||||
if rp, err := s.paths.Add(path); err != nil {
|
||||
glog.Error("ghttp.AddSearchPath failed:", err.Error())
|
||||
return err
|
||||
} else {
|
||||
glog.Debug("ghttp.AddSearchPath:", rp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取
|
||||
|
||||
@ -9,6 +9,7 @@ package ghttp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"strings"
|
||||
"reflect"
|
||||
"fmt"
|
||||
@ -42,6 +43,14 @@ func (s *Server)BindController(pattern string, c Controller, methods...string) e
|
||||
if mname == "Init" || mname == "Shut" || mname == "Exit" {
|
||||
continue
|
||||
}
|
||||
if _, ok := v.Method(i).Interface().(func()); !ok {
|
||||
if methodMap != nil {
|
||||
s := fmt.Sprintf(`invalid medthod definition "%s", while "func()" is required`, v.Method(i).Type().String())
|
||||
glog.Error(s)
|
||||
return errors.New(s)
|
||||
}
|
||||
continue
|
||||
}
|
||||
ctlName := gstr.Replace(t.String(), fmt.Sprintf(`%s.`, pkgName), "")
|
||||
if ctlName[0] == '*' {
|
||||
ctlName = fmt.Sprintf(`(%s)`, ctlName)
|
||||
@ -82,9 +91,15 @@ func (s *Server)BindControllerMethod(pattern string, c Controller, method string
|
||||
t := v.Type()
|
||||
sname := t.Elem().Name()
|
||||
mname := strings.TrimSpace(method)
|
||||
if !v.MethodByName(mname).IsValid() {
|
||||
fval := v.MethodByName(mname)
|
||||
if !fval.IsValid() {
|
||||
return errors.New("invalid method name:" + mname)
|
||||
}
|
||||
if _, ok := fval.Interface().(func()); !ok {
|
||||
s := fmt.Sprintf(`invalid medthod definition "%s", while "func()" is required`, fval.Type().String())
|
||||
glog.Error(s)
|
||||
return errors.New(s)
|
||||
}
|
||||
pkgPath := t.Elem().PkgPath()
|
||||
pkgName := gfile.Basename(pkgPath)
|
||||
ctlName := gstr.Replace(t.String(), fmt.Sprintf(`%s.`, pkgName), "")
|
||||
@ -119,6 +134,11 @@ func (s *Server)BindControllerRest(pattern string, c Controller) error {
|
||||
if _, ok := s.methodsMap[method]; !ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := v.Method(i).Interface().(func()); !ok {
|
||||
s := fmt.Sprintf(`invalid medthod definition "%s", while "func()" is required`, v.Method(i).Type().String())
|
||||
glog.Error(s)
|
||||
return errors.New(s)
|
||||
}
|
||||
pkgName := gfile.Basename(pkgPath)
|
||||
ctlName := gstr.Replace(t.String(), fmt.Sprintf(`%s.`, pkgName), "")
|
||||
if ctlName[0] == '*' {
|
||||
|
||||
@ -9,6 +9,7 @@ package ghttp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"strings"
|
||||
"reflect"
|
||||
"fmt"
|
||||
@ -48,6 +49,15 @@ func (s *Server)BindObject(pattern string, obj interface{}, methods...string) er
|
||||
if mname == "Init" || mname == "Shut" {
|
||||
continue
|
||||
}
|
||||
faddr, ok := v.Method(i).Interface().(func(*Request))
|
||||
if !ok {
|
||||
if methodMap != nil {
|
||||
s := fmt.Sprintf(`invalid medthod definition "%s", while "func(*Request))" is required`, v.Method(i).Type().String())
|
||||
glog.Error(s)
|
||||
return errors.New(s)
|
||||
}
|
||||
continue
|
||||
}
|
||||
objName := gstr.Replace(t.String(), fmt.Sprintf(`%s.`, pkgName), "")
|
||||
if objName[0] == '*' {
|
||||
objName = fmt.Sprintf(`(%s)`, objName)
|
||||
@ -58,7 +68,7 @@ func (s *Server)BindObject(pattern string, obj interface{}, methods...string) er
|
||||
rtype : gROUTE_REGISTER_OBJECT,
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
faddr : faddr,
|
||||
finit : finit,
|
||||
fshut : fshut,
|
||||
}
|
||||
@ -76,7 +86,7 @@ func (s *Server)BindObject(pattern string, obj interface{}, methods...string) er
|
||||
rtype : gROUTE_REGISTER_OBJECT,
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
faddr : faddr,
|
||||
finit : finit,
|
||||
fshut : fshut,
|
||||
}
|
||||
@ -97,6 +107,12 @@ func (s *Server)BindObjectMethod(pattern string, obj interface{}, method string)
|
||||
if !fval.IsValid() {
|
||||
return errors.New("invalid method name:" + mname)
|
||||
}
|
||||
faddr, ok := fval.Interface().(func(*Request))
|
||||
if !ok {
|
||||
s := fmt.Sprintf(`invalid medthod definition "%s", while "func(*Request)" is required`, fval.Type().String())
|
||||
glog.Error(s)
|
||||
return errors.New(s)
|
||||
}
|
||||
finit := (func(*Request))(nil)
|
||||
fshut := (func(*Request))(nil)
|
||||
if v.MethodByName("Init").IsValid() {
|
||||
@ -117,7 +133,7 @@ func (s *Server)BindObjectMethod(pattern string, obj interface{}, method string)
|
||||
rtype : gROUTE_REGISTER_OBJECT,
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : fval.Interface().(func(*Request)),
|
||||
faddr : faddr,
|
||||
finit : finit,
|
||||
fshut : fshut,
|
||||
}
|
||||
@ -146,6 +162,12 @@ func (s *Server)BindObjectRest(pattern string, obj interface{}) error {
|
||||
if _, ok := s.methodsMap[method]; !ok {
|
||||
continue
|
||||
}
|
||||
faddr, ok := v.Method(i).Interface().(func(*Request))
|
||||
if !ok {
|
||||
s := fmt.Sprintf(`invalid medthod definition "%s", while "func()" is required`, v.Method(i).Type().String())
|
||||
glog.Error(s)
|
||||
return errors.New(s)
|
||||
}
|
||||
pkgName := gfile.Basename(pkgPath)
|
||||
objName := gstr.Replace(t.String(), fmt.Sprintf(`%s.`, pkgName), "")
|
||||
if objName[0] == '*' {
|
||||
@ -157,7 +179,7 @@ func (s *Server)BindObjectRest(pattern string, obj interface{}) error {
|
||||
rtype : gROUTE_REGISTER_OBJECT,
|
||||
ctype : nil,
|
||||
fname : "",
|
||||
faddr : v.Method(i).Interface().(func(*Request)),
|
||||
faddr : faddr,
|
||||
finit : finit,
|
||||
fshut : fshut,
|
||||
}
|
||||
|
||||
@ -9,14 +9,14 @@
|
||||
package gcfg
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/container/gvar"
|
||||
"gitee.com/johng/gf/g/os/gspath"
|
||||
"gitee.com/johng/gf/g/os/gfsnotify"
|
||||
"gitee.com/johng/gf/g/container/gmap"
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
"gitee.com/johng/gf/g/container/gtype"
|
||||
"errors"
|
||||
"gitee.com/johng/gf/g/container/gmap"
|
||||
"gitee.com/johng/gf/g/container/gtype"
|
||||
"gitee.com/johng/gf/g/container/gvar"
|
||||
"gitee.com/johng/gf/g/encoding/gjson"
|
||||
"gitee.com/johng/gf/g/os/gfsnotify"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"gitee.com/johng/gf/g/os/gspath"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -37,14 +37,14 @@ func New(path string, file...string) *Config {
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
s := gspath.New()
|
||||
s.Set(path)
|
||||
return &Config {
|
||||
c := &Config {
|
||||
name : gtype.NewString(name),
|
||||
paths : s,
|
||||
paths : gspath.New(),
|
||||
jsons : gmap.NewStringInterfaceMap(),
|
||||
vc : gtype.NewBool(),
|
||||
}
|
||||
c.SetPath(path)
|
||||
return c
|
||||
}
|
||||
|
||||
// 判断从哪个配置文件中获取内容,返回配置文件的绝对路径
|
||||
@ -58,12 +58,13 @@ func (c *Config) filePath(file...string) string {
|
||||
|
||||
// 设置配置管理器的配置文件存放目录绝对路径
|
||||
func (c *Config) SetPath(path string) error {
|
||||
if err := c.paths.Set(path); err != nil {
|
||||
glog.Error("gcfg.SetPath failed:", path, err)
|
||||
if rp, err := c.paths.Set(path); err != nil {
|
||||
glog.Error("gcfg.SetPath failed:", err.Error())
|
||||
return err
|
||||
} else {
|
||||
c.jsons.Clear()
|
||||
glog.Debug("gcfg.SetPath:", rp)
|
||||
}
|
||||
c.jsons.Clear()
|
||||
glog.Debug("gcfg.SetPath:", path)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -76,11 +77,12 @@ func (c *Config) SetViolenceCheck(check bool) {
|
||||
|
||||
// 添加配置管理器的配置文件搜索路径
|
||||
func (c *Config) AddPath(path string) error {
|
||||
if err := c.paths.Add(path); err != nil {
|
||||
glog.Debug("gcfg.AddPath failed:", path, err)
|
||||
if rp, err := c.paths.Add(path); err != nil {
|
||||
glog.Debug("gcfg.AddPath failed:", err.Error())
|
||||
return err
|
||||
} else {
|
||||
glog.Debug("gcfg.AddPath:", rp)
|
||||
}
|
||||
glog.Debug("gcfg.AddPath:", path)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -95,6 +97,7 @@ func (c *Config) GetFilePath(file...string) string {
|
||||
|
||||
// 设置配置管理对象的默认文件名称
|
||||
func (c *Config) SetFileName(name string) {
|
||||
glog.Debug("gcfg.SetFileName:", name)
|
||||
c.name.Set(name)
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ package gspath
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/container/gmap"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g/os/gfsnotify"
|
||||
@ -32,46 +33,52 @@ func New () *SPath {
|
||||
}
|
||||
|
||||
// 设置搜索路径,只保留当前设置项,其他搜索路径被清空
|
||||
func (sp *SPath) Set(path string) error {
|
||||
r := gfile.RealPath(path)
|
||||
if r == "" {
|
||||
r = sp.Search(path)
|
||||
if r == "" {
|
||||
r = gfile.RealPath(gfile.Pwd() + gfile.Separator + path)
|
||||
func (sp *SPath) Set(path string) (realpath string, err error) {
|
||||
realpath = gfile.RealPath(path)
|
||||
if realpath == "" {
|
||||
realpath = sp.Search(path)
|
||||
if realpath == "" {
|
||||
realpath = gfile.RealPath(gfile.Pwd() + gfile.Separator + path)
|
||||
}
|
||||
}
|
||||
if r != "" && gfile.IsDir(r) {
|
||||
r = strings.TrimRight(r, gfile.Separator)
|
||||
if realpath == "" {
|
||||
return realpath, errors.New(fmt.Sprintf(`path "%s" does not exist`, path))
|
||||
}
|
||||
if realpath != "" && gfile.IsDir(realpath) {
|
||||
realpath = strings.TrimRight(realpath, gfile.Separator)
|
||||
sp.mu.Lock()
|
||||
sp.paths = []string{r}
|
||||
sp.paths = []string{realpath}
|
||||
sp.mu.Unlock()
|
||||
sp.cache.Clear()
|
||||
//glog.Debug("gspath.SetPath:", r)
|
||||
return nil
|
||||
return realpath, nil
|
||||
}
|
||||
//glog.Warning("gspath.SetPath failed:", path)
|
||||
return errors.New("invalid path:" + path)
|
||||
return realpath, errors.New("invalid path:" + path)
|
||||
}
|
||||
|
||||
// 添加搜索路径
|
||||
func (sp *SPath) Add(path string) error {
|
||||
r := gfile.RealPath(path)
|
||||
if r == "" {
|
||||
r = sp.Search(path)
|
||||
if r == "" {
|
||||
r = gfile.RealPath(gfile.Pwd() + gfile.Separator + path)
|
||||
func (sp *SPath) Add(path string) (realpath string, err error) {
|
||||
realpath = gfile.RealPath(path)
|
||||
if realpath == "" {
|
||||
realpath = sp.Search(path)
|
||||
if realpath == "" {
|
||||
realpath = gfile.RealPath(gfile.Pwd() + gfile.Separator + path)
|
||||
}
|
||||
}
|
||||
if r != "" && gfile.IsDir(r) {
|
||||
r = strings.TrimRight(r, gfile.Separator)
|
||||
if realpath == "" {
|
||||
return realpath, errors.New(fmt.Sprintf(`path "%s" does not exist`, path))
|
||||
}
|
||||
if realpath != "" && gfile.IsDir(realpath) {
|
||||
realpath = strings.TrimRight(realpath, gfile.Separator)
|
||||
sp.mu.Lock()
|
||||
sp.paths = append(sp.paths, r)
|
||||
sp.paths = append(sp.paths, realpath)
|
||||
sp.mu.Unlock()
|
||||
//glog.Debug("gspath.Add:", r)
|
||||
return nil
|
||||
return realpath, nil
|
||||
}
|
||||
//glog.Warning("gspath.Add failed:", path)
|
||||
return errors.New("invalid path:" + path)
|
||||
return realpath, errors.New("invalid path:" + path)
|
||||
}
|
||||
|
||||
// 按照优先级搜索文件,返回搜索到的文件绝对路径,找不到该文件时,返回空字符串
|
||||
|
||||
@ -25,9 +25,10 @@ const (
|
||||
// "2018-02-09 20:46:17.897",
|
||||
// "2018-02-09T20:46:17Z",
|
||||
// "2018-02-09 20:46:17",
|
||||
// "2018/10/31 - 16:38:46"
|
||||
// "2018-02-09",
|
||||
// 日期连接符号支持'-'或者'/'
|
||||
TIME_REAGEX_PATTERN = `(\d{2,4}[-/]\d{2}[-/]\d{2})[\sT]{0,1}(\d{0,2}:{0,1}\d{0,2}:{0,1}\d{0,2}){0,1}\.{0,1}(\d{0,9})([\sZ]{0,1})([\+-]{0,1})([:\d]*)`
|
||||
TIME_REAGEX_PATTERN = `(\d{2,4}[-/]\d{2}[-/]\d{2})[\sT-]*(\d{0,2}:{0,1}\d{0,2}:{0,1}\d{0,2}){0,1}\.{0,1}(\d{0,9})([\sZ]{0,1})([\+-]{0,1})([:\d]*)`
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@ -8,7 +8,9 @@
|
||||
package gview
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/encoding/gurl"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"gitee.com/johng/gf/g/os/gtime"
|
||||
"gitee.com/johng/gf/g/util/gstr"
|
||||
"strings"
|
||||
@ -70,40 +72,55 @@ func Get(path string) *View {
|
||||
|
||||
// 生成一个视图对象
|
||||
func New(path string) *View {
|
||||
s := gspath.New()
|
||||
s.Set(path)
|
||||
view := &View {
|
||||
paths : s,
|
||||
paths : gspath.New(),
|
||||
data : make(map[string]interface{}),
|
||||
funcmap : make(map[string]interface{}),
|
||||
delimiters : make([]string, 2),
|
||||
}
|
||||
view.SetPath(path)
|
||||
view.SetDelimiters("{{", "}}")
|
||||
// 内置方法
|
||||
view.BindFunc("text", view.funcText)
|
||||
view.BindFunc("html", view.funcHtmlEncode)
|
||||
view.BindFunc("htmlencode", view.funcHtmlEncode)
|
||||
view.BindFunc("htmldecode", view.funcHtmlDecode)
|
||||
//view.BindFunc("htmlchars", view.funcHtmlChars)
|
||||
//view.BindFunc("htmldechars", view.funcHtmlCharsDecode)
|
||||
view.BindFunc("url", view.funcUrlEncode)
|
||||
view.BindFunc("urlencode", view.funcUrlEncode)
|
||||
view.BindFunc("urldecode", view.funcUrlDecode)
|
||||
view.BindFunc("date", view.funcDate)
|
||||
view.BindFunc("substr", view.funcSubStr)
|
||||
view.BindFunc("strlimit", view.funcStrLimit)
|
||||
view.BindFunc("compare", view.funcCompare)
|
||||
view.BindFunc("hidestr", view.funcHideStr)
|
||||
view.BindFunc("highlight", view.funcHighlight)
|
||||
view.BindFunc("toupper", view.funcToUpper)
|
||||
view.BindFunc("tolower", view.funcToLower)
|
||||
view.BindFunc("nl2br", view.funcNl2Br)
|
||||
view.BindFunc("include", view.funcInclude)
|
||||
return view
|
||||
}
|
||||
|
||||
// 设置模板目录绝对路径
|
||||
func (view *View) SetPath(path string) error {
|
||||
return view.paths.Set(path)
|
||||
if rp, err := view.paths.Set(path); err != nil {
|
||||
glog.Error("gview.SetPath failed:", err.Error())
|
||||
return err
|
||||
} else {
|
||||
glog.Debug("gview.SetPath:", rp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 添加模板目录搜索路径
|
||||
func (view *View) AddPath(path string) error {
|
||||
return view.paths.Add(path)
|
||||
if rp, err := view.paths.Add(path); err != nil {
|
||||
glog.Error("gview.AddPath failed:", err.Error())
|
||||
return err
|
||||
} else {
|
||||
glog.Debug("gview.SetPath:", rp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 批量绑定模板变量,即调用之后每个线程都会生效,因此有并发安全控制
|
||||
@ -244,16 +261,6 @@ func (view *View) funcHtmlDecode(html interface{}) string {
|
||||
return ghtml.EntitiesDecode(gconv.String(html))
|
||||
}
|
||||
|
||||
// 模板内置方法:htmlchars
|
||||
func (view *View) funcHtmlChars(html interface{}) string {
|
||||
return ghtml.SpecialChars(gconv.String(html))
|
||||
}
|
||||
|
||||
// 模板内置方法:htmlcharsdecode
|
||||
func (view *View) funcHtmlCharsDecode(html interface{}) string {
|
||||
return ghtml.SpecialCharsDecode(gconv.String(html))
|
||||
}
|
||||
|
||||
// 模板内置方法:url
|
||||
func (view *View) funcUrlEncode(url interface{}) string {
|
||||
return gurl.Encode(gconv.String(url))
|
||||
@ -283,4 +290,34 @@ func (view *View) funcSubStr(start, end int, str interface{}) string {
|
||||
return gstr.SubStr(gconv.String(str), start, end)
|
||||
}
|
||||
|
||||
// 模板内置方法:strlimit
|
||||
func (view *View) funcStrLimit(length int, suffix string, str interface{}) string {
|
||||
return gstr.StrLimit(gconv.String(str), length, suffix)
|
||||
}
|
||||
|
||||
// 模板内置方法:highlight
|
||||
func (view *View) funcHighlight(key string, color string, str interface{}) string {
|
||||
return gstr.Replace(gconv.String(str), key, fmt.Sprintf(`<span style="color:%s;">%s</span>`, color, key))
|
||||
}
|
||||
|
||||
// 模板内置方法:hidestr
|
||||
func (view *View) funcHideStr(percent int, hide string, str interface{}) string {
|
||||
return gstr.HideStr(gconv.String(str), percent, hide)
|
||||
}
|
||||
|
||||
// 模板内置方法:toupper
|
||||
func (view *View) funcToUpper(str interface{}) string {
|
||||
return gstr.ToUpper(gconv.String(str))
|
||||
}
|
||||
|
||||
// 模板内置方法:toupper
|
||||
func (view *View) funcToLower(str interface{}) string {
|
||||
return gstr.ToLower(gconv.String(str))
|
||||
}
|
||||
|
||||
// 模板内置方法:nl2br
|
||||
func (view *View) funcNl2Br(str interface{}) string {
|
||||
return gstr.Nl2Br(gconv.String(str))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/container/gset"
|
||||
"gitee.com/johng/gf/g/util/gstr"
|
||||
"reflect"
|
||||
"gitee.com/johng/gf/third/github.com/fatih/structs"
|
||||
@ -83,16 +84,38 @@ func Struct(params interface{}, objPointer interface{}, attrMapping...map[string
|
||||
}
|
||||
}
|
||||
// 最后按照默认规则进行匹配
|
||||
attrset := gset.NewStringSet(false)
|
||||
elemtype := elem.Type()
|
||||
for i := 0; i < elem.NumField(); i++ {
|
||||
attrset.Add(elemtype.Field(i).Name)
|
||||
}
|
||||
for mapk, mapv := range paramsMap {
|
||||
name := gstr.UcFirst(mapk)
|
||||
if _, ok := dmap[name]; ok {
|
||||
name := ""
|
||||
for _, v := range []string{gstr.UcFirst(mapk), gstr.ToLower(mapk), gstr.ToUpper(mapk)} {
|
||||
if _, ok := dmap[v]; ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := tagmap[v]; ok {
|
||||
continue
|
||||
}
|
||||
// 循环查找属性名称进行匹配
|
||||
attrset.Iterator(func(value string) bool {
|
||||
if strings.EqualFold(value, v) {
|
||||
name = value
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
if name != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
// 如果没有匹配到属性名称,放弃
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
// 后续tag逻辑中会处理的key(重复的键名)这里便不处理
|
||||
if _, ok := tagmap[mapk]; !ok {
|
||||
if err := bindVarToStruct(elem, name, mapv); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bindVarToStruct(elem, name, mapv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -120,7 +143,7 @@ func getTagMapOfStruct(objPointer interface{}) map[string]string {
|
||||
}
|
||||
|
||||
// 将参数值绑定到对象指定名称的属性上
|
||||
func bindVarToStruct(elem reflect.Value, name string, value interface{}) error {
|
||||
func bindVarToStruct(elem reflect.Value, name string, value interface{}) (err error) {
|
||||
structFieldValue := elem.FieldByName(name)
|
||||
// 键名与对象属性匹配检测,map中如果有struct不存在的属性,那么不做处理,直接return
|
||||
if !structFieldValue.IsValid() {
|
||||
@ -136,7 +159,7 @@ func bindVarToStruct(elem reflect.Value, name string, value interface{}) error {
|
||||
defer func() {
|
||||
// 如果转换失败,那么可能是类型不匹配造成(例如属性包含自定义类型),那么执行递归转换
|
||||
if recover() != nil {
|
||||
bindVarToStructIfDefaultConvertionFailed(structFieldValue, value)
|
||||
err = bindVarToStructIfDefaultConvertionFailed(structFieldValue, value)
|
||||
}
|
||||
}()
|
||||
structFieldValue.Set(reflect.ValueOf(Convert(value, structFieldValue.Type().String())))
|
||||
@ -144,7 +167,7 @@ func bindVarToStruct(elem reflect.Value, name string, value interface{}) error {
|
||||
}
|
||||
|
||||
// 将参数值绑定到对象指定索引位置的属性上
|
||||
func bindVarToStructByIndex(elem reflect.Value, index int, value interface{}) error {
|
||||
func bindVarToStructByIndex(elem reflect.Value, index int, value interface{}) (err error) {
|
||||
structFieldValue := elem.FieldByIndex([]int{index})
|
||||
// 键名与对象属性匹配检测
|
||||
if !structFieldValue.IsValid() {
|
||||
@ -160,7 +183,7 @@ func bindVarToStructByIndex(elem reflect.Value, index int, value interface{}) er
|
||||
defer func() {
|
||||
// 如果转换失败,那么可能是类型不匹配造成(例如属性包含自定义类型),那么执行递归转换
|
||||
if recover() != nil {
|
||||
bindVarToStructIfDefaultConvertionFailed(structFieldValue, value)
|
||||
err = bindVarToStructIfDefaultConvertionFailed(structFieldValue, value)
|
||||
}
|
||||
}()
|
||||
structFieldValue.Set(reflect.ValueOf(Convert(value, structFieldValue.Type().String())))
|
||||
@ -168,7 +191,7 @@ func bindVarToStructByIndex(elem reflect.Value, index int, value interface{}) er
|
||||
}
|
||||
|
||||
// 当默认的基本类型转换失败时,通过recover判断后执行反射类型转换
|
||||
func bindVarToStructIfDefaultConvertionFailed(structFieldValue reflect.Value, value interface{}) {
|
||||
func bindVarToStructIfDefaultConvertionFailed(structFieldValue reflect.Value, value interface{}) error {
|
||||
switch structFieldValue.Kind() {
|
||||
case reflect.Struct:
|
||||
Struct(value, structFieldValue)
|
||||
@ -190,7 +213,8 @@ func bindVarToStructIfDefaultConvertionFailed(structFieldValue reflect.Value, va
|
||||
}
|
||||
structFieldValue.Set(a)
|
||||
default:
|
||||
panic(errors.New(fmt.Sprintf(`cannot convert to type "%s"`, structFieldValue.Type().String())))
|
||||
return errors.New(fmt.Sprintf(`cannot convert to type "%s"`, structFieldValue.Type().String()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
137
g/util/gconv/gconv_test.go
Normal file
137
g/util/gconv/gconv_test.go
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright 2017-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.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var value = 123456789
|
||||
|
||||
func BenchmarkString(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
String(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int8(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int16(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int32(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInt64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Int(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint8(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint16(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint16(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint32(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUint64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Uint64(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFloat32(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float32(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFloat64(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Float64(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func BenchmarkTime(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Time(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTimeDuration(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
TimeDuration(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func BenchmarkBytes(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Bytes(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStrings(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Strings(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInts(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Ints(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFloats(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Floats(value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInterfaces(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Interfaces(value)
|
||||
}
|
||||
}
|
||||
@ -8,12 +8,12 @@
|
||||
package gregex
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/container/gmap"
|
||||
"regexp"
|
||||
"gitee.com/johng/gf/g/os/gcache"
|
||||
)
|
||||
|
||||
// 缓存对象,主要用于缓存底层regx对象
|
||||
var regxCache = gcache.New()
|
||||
var regxCache = gmap.NewStringInterfaceMap(true)
|
||||
|
||||
// 根据pattern生成对应的regexp正则对象
|
||||
func getRegexp(pattern string) (*regexp.Regexp, error) {
|
||||
@ -21,7 +21,7 @@ func getRegexp(pattern string) (*regexp.Regexp, error) {
|
||||
return v.(*regexp.Regexp), nil
|
||||
}
|
||||
if r, err := regexp.Compile(pattern); err == nil {
|
||||
regxCache.Set(pattern, r, 0)
|
||||
regxCache.Set(pattern, r)
|
||||
return r, nil
|
||||
} else {
|
||||
return nil, err
|
||||
|
||||
@ -7,11 +7,19 @@
|
||||
// 字符串操作.
|
||||
package gstr
|
||||
|
||||
import "strings"
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 字符串替换
|
||||
func Replace(origin, search, replace string) string {
|
||||
return strings.Replace(origin, search, replace, -1)
|
||||
func Replace(origin, search, replace string, count...int) string {
|
||||
n := -1
|
||||
if len(count) > 0 {
|
||||
n = count[0]
|
||||
}
|
||||
return strings.Replace(origin, search, replace, n)
|
||||
}
|
||||
|
||||
// 使用map进行字符串替换
|
||||
@ -23,6 +31,16 @@ func ReplaceByMap(origin string, replaces map[string]string) string {
|
||||
return result
|
||||
}
|
||||
|
||||
// 字符串转换为小写
|
||||
func ToLower(s string) string {
|
||||
return strings.ToLower(s)
|
||||
}
|
||||
|
||||
// 字符串转换为大写
|
||||
func ToUpper(s string) string {
|
||||
return strings.ToUpper(s)
|
||||
}
|
||||
|
||||
// 字符串首字母转换为大写
|
||||
func UcFirst(s string) string {
|
||||
if len(s) == 0 {
|
||||
@ -110,4 +128,51 @@ func SubStr(str string, start int, length...int) (substr string) {
|
||||
}
|
||||
// 返回子串
|
||||
return string(rs[start : end])
|
||||
}
|
||||
|
||||
// 字符串长度截取限制,超过长度限制被截取并在字符串末尾追加指定的内容,支持中文
|
||||
func StrLimit(str string, length int, suffix...string) (string) {
|
||||
rs := []rune(str)
|
||||
if len(str) < length {
|
||||
return str
|
||||
}
|
||||
addstr := "..."
|
||||
if len(suffix) > 0 {
|
||||
addstr = suffix[0]
|
||||
}
|
||||
return string(rs[0 : length]) + addstr
|
||||
}
|
||||
|
||||
// 按照百分比从字符串中间向两边隐藏字符(主要用于姓名、手机号、邮箱地址、身份证号等的隐藏),支持utf-8中文,支持email格式。
|
||||
func HideStr(str string, percent int, hide string) string {
|
||||
array := strings.Split(str, "@")
|
||||
if len(array) > 1 {
|
||||
str = array[0]
|
||||
}
|
||||
rs := []rune(str)
|
||||
length := len(rs)
|
||||
mid := math.Floor(float64(length/2))
|
||||
hideLen := int(math.Floor(float64(length) * (float64(percent)/100)))
|
||||
start := int(mid - math.Floor(float64(hideLen) / 2))
|
||||
hideStr := []rune("")
|
||||
hideRune := []rune(hide)
|
||||
for i := 0; i < int(hideLen); i++ {
|
||||
hideStr = append(hideStr, hideRune...)
|
||||
}
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
buffer.WriteString(string(rs[0 : start]))
|
||||
buffer.WriteString(string(hideStr))
|
||||
buffer.WriteString(string(rs[start + hideLen : ]))
|
||||
if len(array) > 1 {
|
||||
buffer.WriteString(array[1])
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// 将\n\r替换为html中的<br>标签。
|
||||
func Nl2Br(str string) string {
|
||||
str = Replace(str, "\r\n", "\n")
|
||||
str = Replace(str, "\n\r", "\n")
|
||||
str = Replace(str, "\n", "<br />")
|
||||
return str
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/frame/gmvc"
|
||||
"gitee.com/johng/gf/g"
|
||||
"gitee.com/johng/gf/g/frame/gmvc"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
@ -13,8 +13,13 @@ func (c *User) Index() {
|
||||
c.View.Display("index.html")
|
||||
}
|
||||
|
||||
// 不符合规范,不会被自动注册
|
||||
func (c *User) Test(value interface{}) {
|
||||
c.View.Display("index.html")
|
||||
}
|
||||
|
||||
func main() {
|
||||
g.View().SetPath("C:/www/static")
|
||||
//g.View().SetPath("C:/www/static")
|
||||
s := g.Server()
|
||||
s.BindController("/user", new(User))
|
||||
s.SetPort(8199)
|
||||
|
||||
31
geg/net/ghttp/server/object/user.go
Normal file
31
geg/net/ghttp/server/object/user.go
Normal file
@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g"
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
|
||||
}
|
||||
|
||||
func (c *User) Index(r *ghttp.Request) {
|
||||
r.Response.Write("Index")
|
||||
}
|
||||
|
||||
// 不符合规范,不会被注册
|
||||
func (c *User) Test(r *ghttp.Request, value interface{}) {
|
||||
r.Response.Write("Test")
|
||||
}
|
||||
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.BindObjectMethod("/user", new(User), "Test")
|
||||
s.SetPort(8199)
|
||||
s.Run()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ func main() {
|
||||
"2018-02-09 20:46:17.897",
|
||||
"2018-02-09T20:46:17Z",
|
||||
"2018-02-09 20:46:17",
|
||||
"2018/10/31 - 16:38:46",
|
||||
"2018-02-09",
|
||||
"2017/12/14 04:51:34 +0805 LMT",
|
||||
"2018/02/09 12:00:15",
|
||||
|
||||
@ -20,6 +20,13 @@ func main() {
|
||||
{{compare 1 1}}
|
||||
{{"我是中国人" | substr 2 -1}}
|
||||
{{"我是中国人" | substr 2 2}}
|
||||
{{"我是中国人" | strlimit 2 "..."}}
|
||||
{{"热爱GF热爱生活" | hidestr 20 "*"}}
|
||||
{{"热爱GF热爱生活" | hidestr 50 "*"}}
|
||||
{{"热爱GF热爱生活" | highlight "GF" "red"}}
|
||||
{{"gf" | toupper}}
|
||||
{{"GF" | tolower}}
|
||||
{{"Go\nFrame" | nl2br}}
|
||||
`
|
||||
content, err := g.View().ParseContent(tplContent, nil)
|
||||
fmt.Println(err)
|
||||
|
||||
@ -1,10 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g"
|
||||
"gitee.com/johng/gf/g/net/ghttp"
|
||||
)
|
||||
|
||||
|
||||
func main() {
|
||||
fmt.Println(gfile.Dir("c:\111\222"))
|
||||
s := g.Server()
|
||||
s.Domain("www.a.com").BindHandler("/*", func(r *ghttp.Request) {
|
||||
r.Response.ServeFile("/home/john/www1" + r.URL.Path)
|
||||
})
|
||||
s.Domain("www.b.com").BindHandler("/*", func(r *ghttp.Request) {
|
||||
r.Response.ServeFile("/home/john/www2" + r.URL.Path)
|
||||
})
|
||||
s.SetIndexFolder(true)
|
||||
s.SetPort(8080)
|
||||
s.Run()
|
||||
}
|
||||
@ -16,13 +16,13 @@ type User struct {
|
||||
func main() {
|
||||
user := (*User)(nil)
|
||||
|
||||
// 使用map直接映射绑定属性值到对象
|
||||
// 使用默认映射规则绑定属性值到对象
|
||||
user = new(User)
|
||||
params1 := g.Map{
|
||||
"uid" : 1,
|
||||
"name" : "john",
|
||||
"pass1" : "123",
|
||||
"pass2" : "123",
|
||||
"Name" : "john",
|
||||
"PASS1" : "123",
|
||||
"PaSs2" : "456",
|
||||
}
|
||||
if err := gconv.Struct(params1, user); err == nil {
|
||||
fmt.Println(user)
|
||||
@ -33,8 +33,8 @@ func main() {
|
||||
params2 := g.Map {
|
||||
"uid" : 2,
|
||||
"name" : "smith",
|
||||
"password1" : "456",
|
||||
"password2" : "456",
|
||||
"password1" : "111",
|
||||
"password2" : "222",
|
||||
}
|
||||
if err := gconv.Struct(params2, user); err == nil {
|
||||
fmt.Println(user)
|
||||
|
||||
@ -1,31 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/util/gconv"
|
||||
"gitee.com/johng/gf/g"
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g"
|
||||
"gitee.com/johng/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
// 演示slice类型属性的赋值
|
||||
|
||||
// 使用默认映射规则绑定属性值到对象
|
||||
func main() {
|
||||
type User struct {
|
||||
Scores []int
|
||||
Uid int
|
||||
Name string
|
||||
Pass1 string
|
||||
Pass2 string
|
||||
}
|
||||
|
||||
user := new(User)
|
||||
scores := []interface{}{99, 100, 60, 140}
|
||||
|
||||
// 通过map映射转换
|
||||
if err := gconv.Struct(g.Map{"Scores" : scores}, user); err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
g.Dump(user)
|
||||
user := new(User)
|
||||
params := g.Map {
|
||||
"uid" : 1,
|
||||
"Name" : "john",
|
||||
"PASS1" : "123",
|
||||
"PASS2" : "456",
|
||||
}
|
||||
|
||||
// 通过变量映射转换,直接slice赋值
|
||||
if err := gconv.Struct(scores, user); err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
g.Dump(user)
|
||||
if err := gconv.Struct(params, user); err == nil {
|
||||
fmt.Println(user)
|
||||
}
|
||||
}
|
||||
@ -6,24 +6,23 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 演示slice类型属性的赋值
|
||||
func main() {
|
||||
type Score struct {
|
||||
Name string
|
||||
Result int
|
||||
}
|
||||
type User struct {
|
||||
Scores Score
|
||||
Scores []int
|
||||
}
|
||||
|
||||
user := new(User)
|
||||
scores := map[string]interface{}{
|
||||
"Scores" : map[string]interface{}{
|
||||
"Name" : "john",
|
||||
"Result" : 100,
|
||||
},
|
||||
scores := []interface{}{99, 100, 60, 140}
|
||||
|
||||
// 通过map映射转换
|
||||
if err := gconv.Struct(g.Map{"Scores" : scores}, user); err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
g.Dump(user)
|
||||
}
|
||||
|
||||
// 嵌套struct转换
|
||||
// 通过变量映射转换,直接slice赋值
|
||||
if err := gconv.Struct(scores, user); err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
|
||||
@ -12,7 +12,7 @@ func main() {
|
||||
Result int
|
||||
}
|
||||
type User struct {
|
||||
Scores []Score
|
||||
Scores Score
|
||||
}
|
||||
|
||||
user := new(User)
|
||||
@ -23,7 +23,7 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
// 嵌套struct转换,属性为slice类型,数值为map类型
|
||||
// 嵌套struct转换
|
||||
if err := gconv.Struct(scores, user); err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
|
||||
@ -17,19 +17,13 @@ func main() {
|
||||
|
||||
user := new(User)
|
||||
scores := map[string]interface{}{
|
||||
"Scores" : []interface{}{
|
||||
map[string]interface{}{
|
||||
"Name" : "john",
|
||||
"Result" : 100,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"Name" : "smith",
|
||||
"Result" : 60,
|
||||
},
|
||||
"Scores" : map[string]interface{}{
|
||||
"Name" : "john",
|
||||
"Result" : 100,
|
||||
},
|
||||
}
|
||||
|
||||
// 嵌套struct转换,属性为slice类型,数值为slice map类型
|
||||
// 嵌套struct转换,属性为slice类型,数值为map类型
|
||||
if err := gconv.Struct(scores, user); err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
|
||||
38
geg/util/gconv/gconv_struct6.go
Normal file
38
geg/util/gconv/gconv_struct6.go
Normal file
@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/util/gconv"
|
||||
"gitee.com/johng/gf/g"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type Score struct {
|
||||
Name string
|
||||
Result int
|
||||
}
|
||||
type User struct {
|
||||
Scores []Score
|
||||
}
|
||||
|
||||
user := new(User)
|
||||
scores := map[string]interface{}{
|
||||
"Scores" : []interface{}{
|
||||
map[string]interface{}{
|
||||
"Name" : "john",
|
||||
"Result" : 100,
|
||||
},
|
||||
map[string]interface{}{
|
||||
"Name" : "smith",
|
||||
"Result" : 60,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// 嵌套struct转换,属性为slice类型,数值为slice map类型
|
||||
if err := gconv.Struct(scores, user); err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
g.Dump(user)
|
||||
}
|
||||
}
|
||||
11
geg/util/gstr/gstr_hidestr.go
Normal file
11
geg/util/gstr/gstr_hidestr.go
Normal file
@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/util/gstr"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(gstr.HideStr("热爱GF热爱生活", 20, "*"))
|
||||
fmt.Println(gstr.HideStr("热爱GF热爱生活", 50, "*"))
|
||||
}
|
||||
Reference in New Issue
Block a user