mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
add MapMerge/MapMargeCopy functions for package gutil; improve template view feature for indefinite parameters
This commit is contained in:
@ -99,7 +99,7 @@ func (view *View) BindFuncMap(funcMap gview.FuncMap) {
|
||||
|
||||
// Display parses and writes the parsed template file content to http response.
|
||||
func (view *View) Display(file ...string) error {
|
||||
name := "index.tpl"
|
||||
name := view.view.GetDefaultFile()
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"github.com/gogf/gf/os/gcfg"
|
||||
"github.com/gogf/gf/os/gview"
|
||||
"github.com/gogf/gf/util/gmode"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
)
|
||||
|
||||
// WriteTpl parses and responses given template file.
|
||||
@ -74,27 +75,19 @@ func (r *Response) ParseTplContent(content string, params ...gview.Params) (stri
|
||||
|
||||
// buildInVars merges build-in variables into <params> and returns the new template variables.
|
||||
func (r *Response) buildInVars(params ...map[string]interface{}) map[string]interface{} {
|
||||
var vars map[string]interface{}
|
||||
if len(params) > 0 && params[0] != nil {
|
||||
vars = params[0]
|
||||
} else {
|
||||
vars = make(map[string]interface{})
|
||||
}
|
||||
m := gutil.MapMergeCopy(params...)
|
||||
// Retrieve custom template variables from request object.
|
||||
if len(r.Request.viewParams) > 0 {
|
||||
for k, v := range r.Request.viewParams {
|
||||
vars[k] = v
|
||||
}
|
||||
}
|
||||
gutil.MapMerge(m, r.Request.viewParams, map[string]interface{}{
|
||||
"Form": r.Request.GetFormMap(),
|
||||
"Query": r.Request.GetQueryMap(),
|
||||
"Request": r.Request.GetMap(),
|
||||
"Cookie": r.Request.Cookie.Map(),
|
||||
"Session": r.Request.Session.Map(),
|
||||
})
|
||||
// Note that it should assign no Config variable to template
|
||||
// if there's no configuration file.
|
||||
if c := gcfg.Instance(); c.Available() {
|
||||
vars["Config"] = c.GetMap(".")
|
||||
m["Config"] = c.GetMap(".")
|
||||
}
|
||||
vars["Form"] = r.Request.GetFormMap()
|
||||
vars["Query"] = r.Request.GetQueryMap()
|
||||
vars["Request"] = r.Request.GetMap()
|
||||
vars["Cookie"] = r.Request.Cookie.Map()
|
||||
vars["Session"] = r.Request.Session.Map()
|
||||
return vars
|
||||
return m
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ package gview
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/i18n/gi18n"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
|
||||
"github.com/gogf/gf"
|
||||
@ -28,21 +27,12 @@ type View struct {
|
||||
data map[string]interface{} // Global template variables.
|
||||
funcMap map[string]interface{} // Global template function map.
|
||||
fileCacheMap *gmap.StrAnyMap // File cache map.
|
||||
defaultFile string // Default template file for parsing.
|
||||
i18nManager *gi18n.Manager // I18n manager for this view.
|
||||
delimiters []string // Custom template delimiters.
|
||||
config Config // Extra configuration for the view.
|
||||
}
|
||||
|
||||
// Params is type for template params.
|
||||
type Params = map[string]interface{}
|
||||
|
||||
// FuncMap is type for custom template functions.
|
||||
type FuncMap = map[string]interface{}
|
||||
|
||||
const (
|
||||
// Default template file for parsing.
|
||||
defaultParsingFile = "index.html"
|
||||
type (
|
||||
Params = map[string]interface{} // Params is type for template params.
|
||||
FuncMap = map[string]interface{} // FuncMap is type for custom template functions.
|
||||
)
|
||||
|
||||
var (
|
||||
@ -60,9 +50,9 @@ func checkAndInitDefaultView() {
|
||||
|
||||
// ParseContent parses the template content directly using the default view object
|
||||
// and returns the parsed content.
|
||||
func ParseContent(content string, params Params) (string, error) {
|
||||
func ParseContent(content string, params ...Params) (string, error) {
|
||||
checkAndInitDefaultView()
|
||||
return defaultViewObj.ParseContent(content, params)
|
||||
return defaultViewObj.ParseContent(content, params...)
|
||||
}
|
||||
|
||||
// New returns a new view object.
|
||||
@ -73,9 +63,7 @@ func New(path ...string) *View {
|
||||
data: make(map[string]interface{}),
|
||||
funcMap: make(map[string]interface{}),
|
||||
fileCacheMap: gmap.NewStrAnyMap(true),
|
||||
defaultFile: defaultParsingFile,
|
||||
i18nManager: gi18n.Instance(),
|
||||
delimiters: make([]string, 2),
|
||||
config: DefaultConfig(),
|
||||
}
|
||||
if len(path) > 0 && len(path[0]) > 0 {
|
||||
if err := view.SetPath(path[0]); err != nil {
|
||||
@ -118,35 +106,36 @@ func New(path ...string) *View {
|
||||
"version": gf.VERSION,
|
||||
}
|
||||
// default build-in functions.
|
||||
view.BindFunc("eq", view.funcEq)
|
||||
view.BindFunc("ne", view.funcNe)
|
||||
view.BindFunc("lt", view.funcLt)
|
||||
view.BindFunc("le", view.funcLe)
|
||||
view.BindFunc("gt", view.funcGt)
|
||||
view.BindFunc("ge", view.funcGe)
|
||||
view.BindFunc("text", view.funcText)
|
||||
view.BindFuncMap(FuncMap{
|
||||
"eq": view.funcEq,
|
||||
"ne": view.funcNe,
|
||||
"lt": view.funcLt,
|
||||
"le": view.funcLe,
|
||||
"gt": view.funcGt,
|
||||
"ge": view.funcGe,
|
||||
"text": view.funcText,
|
||||
"html": view.funcHtmlEncode,
|
||||
"htmlencode": view.funcHtmlEncode,
|
||||
"htmldecode": view.funcHtmlDecode,
|
||||
"encode": view.funcHtmlEncode,
|
||||
"decode": view.funcHtmlDecode,
|
||||
"url": view.funcUrlEncode,
|
||||
"urlencode": view.funcUrlEncode,
|
||||
"urldecode": view.funcUrlDecode,
|
||||
"date": view.funcDate,
|
||||
"substr": view.funcSubStr,
|
||||
"strlimit": view.funcStrLimit,
|
||||
"concat": view.funcConcat,
|
||||
"replace": view.funcReplace,
|
||||
"compare": view.funcCompare,
|
||||
"hidestr": view.funcHideStr,
|
||||
"highlight": view.funcHighlight,
|
||||
"toupper": view.funcToUpper,
|
||||
"tolower": view.funcToLower,
|
||||
"nl2br": view.funcNl2Br,
|
||||
"include": view.funcInclude,
|
||||
"dump": view.funcDump,
|
||||
})
|
||||
|
||||
view.BindFunc("html", view.funcHtmlEncode)
|
||||
view.BindFunc("htmlencode", view.funcHtmlEncode)
|
||||
view.BindFunc("htmldecode", view.funcHtmlDecode)
|
||||
view.BindFunc("encode", view.funcHtmlEncode)
|
||||
view.BindFunc("decode", view.funcHtmlDecode)
|
||||
|
||||
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("concat", view.funcConcat)
|
||||
view.BindFunc("replace", view.funcReplace)
|
||||
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)
|
||||
view.BindFunc("dump", view.funcDump)
|
||||
return view
|
||||
}
|
||||
|
||||
@ -22,10 +22,25 @@ import (
|
||||
// Config is the configuration object for template engine.
|
||||
type Config struct {
|
||||
Paths []string // Searching array for path, NOT concurrent-safe for performance purpose.
|
||||
Data map[string]interface{} // Global template variables.
|
||||
Data map[string]interface{} // Global template variables including configuration.
|
||||
DefaultFile string // Default template file for parsing.
|
||||
Delimiters []string // Custom template delimiters.
|
||||
AutoEncode bool // Automatically encodes and provides safe html output, which is good for avoiding XSS.
|
||||
I18nManager *gi18n.Manager // I18n manager for the view.
|
||||
}
|
||||
|
||||
const (
|
||||
// Default template file for parsing.
|
||||
defaultParsingFile = "index.html"
|
||||
)
|
||||
|
||||
// DefaultConfig creates and returns a configuration object with default configurations.
|
||||
func DefaultConfig() Config {
|
||||
return Config{
|
||||
DefaultFile: defaultParsingFile,
|
||||
I18nManager: gi18n.Instance(),
|
||||
Delimiters: make([]string, 2),
|
||||
}
|
||||
}
|
||||
|
||||
// SetConfig sets the configuration for view.
|
||||
@ -199,13 +214,17 @@ func (view *View) Assign(key string, value interface{}) {
|
||||
|
||||
// SetDefaultFile sets default template file for parsing.
|
||||
func (view *View) SetDefaultFile(file string) {
|
||||
view.defaultFile = file
|
||||
view.config.DefaultFile = file
|
||||
}
|
||||
|
||||
// GetDefaultFile returns default template file for parsing.
|
||||
func (view *View) GetDefaultFile() string {
|
||||
return view.config.DefaultFile
|
||||
}
|
||||
|
||||
// SetDelimiters sets customized delimiters for template parsing.
|
||||
func (view *View) SetDelimiters(left, right string) {
|
||||
view.delimiters[0] = left
|
||||
view.delimiters[1] = right
|
||||
view.config.Delimiters = []string{left, right}
|
||||
}
|
||||
|
||||
// SetAutoEncode enables/disables automatically html encoding feature.
|
||||
@ -237,5 +256,5 @@ func (view *View) BindFuncMap(funcMap FuncMap) {
|
||||
|
||||
// SetI18n binds i18n manager to current view engine.
|
||||
func (view *View) SetI18n(manager *gi18n.Manager) {
|
||||
view.i18nManager = manager
|
||||
view.config.I18nManager = manager
|
||||
}
|
||||
|
||||
@ -10,14 +10,14 @@ import "github.com/gogf/gf/util/gconv"
|
||||
|
||||
// i18nTranslate translate the content with i18n feature.
|
||||
func (view *View) i18nTranslate(content string, params Params) string {
|
||||
if view.i18nManager != nil {
|
||||
if view.config.I18nManager != nil {
|
||||
if v, ok := params["I18nLanguage"]; ok {
|
||||
language := gconv.String(v)
|
||||
if language != "" {
|
||||
return view.i18nManager.T(content, language)
|
||||
return view.config.I18nManager.T(content, language)
|
||||
}
|
||||
}
|
||||
return view.i18nManager.T(content)
|
||||
return view.config.I18nManager.T(content)
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import (
|
||||
"github.com/gogf/gf/os/gmlock"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
htmltpl "html/template"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -113,32 +114,9 @@ func (view *View) Parse(file string, params ...Params) (result string, err error
|
||||
// Note that the template variable assignment cannot change the value
|
||||
// of the existing <params> or view.data because both variables are pointers.
|
||||
// It needs to merge the values of the two maps into a new map.
|
||||
var variables map[string]interface{}
|
||||
length := len(view.data)
|
||||
if len(params) > 0 {
|
||||
length += len(params[0])
|
||||
}
|
||||
if length > 0 {
|
||||
variables = make(map[string]interface{}, length)
|
||||
}
|
||||
variables := gutil.MapMergeCopy(params...)
|
||||
if len(view.data) > 0 {
|
||||
if len(params) > 0 {
|
||||
if variables == nil {
|
||||
variables = make(map[string]interface{})
|
||||
}
|
||||
for k, v := range params[0] {
|
||||
variables[k] = v
|
||||
}
|
||||
for k, v := range view.data {
|
||||
variables[k] = v
|
||||
}
|
||||
} else {
|
||||
variables = view.data
|
||||
}
|
||||
} else {
|
||||
if len(params) > 0 {
|
||||
variables = params[0]
|
||||
}
|
||||
gutil.MapMerge(variables, view.data)
|
||||
}
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if view.config.AutoEncode {
|
||||
@ -163,7 +141,7 @@ func (view *View) Parse(file string, params ...Params) (result string, err error
|
||||
|
||||
// ParseDefault parses the default template file with params.
|
||||
func (view *View) ParseDefault(params ...Params) (result string, err error) {
|
||||
return view.Parse(view.defaultFile, params...)
|
||||
return view.Parse(view.config.DefaultFile, params...)
|
||||
}
|
||||
|
||||
// ParseContent parses given template content <content> with template variables <params>
|
||||
@ -174,12 +152,18 @@ func (view *View) ParseContent(content string, params ...Params) (string, error)
|
||||
return "", nil
|
||||
}
|
||||
err := (error)(nil)
|
||||
key := fmt.Sprintf("%s_%v_%v", gCONTENT_TEMPLATE_NAME, view.delimiters, view.config.AutoEncode)
|
||||
key := fmt.Sprintf("%s_%v_%v", gCONTENT_TEMPLATE_NAME, view.config.Delimiters, view.config.AutoEncode)
|
||||
tpl := templates.GetOrSetFuncLock(key, func() interface{} {
|
||||
if view.config.AutoEncode {
|
||||
return htmltpl.New(gCONTENT_TEMPLATE_NAME).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcMap)
|
||||
return htmltpl.New(gCONTENT_TEMPLATE_NAME).Delims(
|
||||
view.config.Delimiters[0],
|
||||
view.config.Delimiters[1],
|
||||
).Funcs(view.funcMap)
|
||||
}
|
||||
return texttpl.New(gCONTENT_TEMPLATE_NAME).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcMap)
|
||||
return texttpl.New(gCONTENT_TEMPLATE_NAME).Delims(
|
||||
view.config.Delimiters[0],
|
||||
view.config.Delimiters[1],
|
||||
).Funcs(view.funcMap)
|
||||
})
|
||||
// Using memory lock to ensure concurrent safety for content parsing.
|
||||
hash := strconv.FormatUint(ghash.DJBHash64([]byte(content)), 10)
|
||||
@ -196,32 +180,9 @@ func (view *View) ParseContent(content string, params ...Params) (string, error)
|
||||
// Note that the template variable assignment cannot change the value
|
||||
// of the existing <params> or view.data because both variables are pointers.
|
||||
// It needs to merge the values of the two maps into a new map.
|
||||
var variables map[string]interface{}
|
||||
length := len(view.data)
|
||||
if len(params) > 0 {
|
||||
length += len(params[0])
|
||||
}
|
||||
if length > 0 {
|
||||
variables = make(map[string]interface{}, length)
|
||||
}
|
||||
variables := gutil.MapMergeCopy(params...)
|
||||
if len(view.data) > 0 {
|
||||
if len(params) > 0 {
|
||||
if variables == nil {
|
||||
variables = make(map[string]interface{})
|
||||
}
|
||||
for k, v := range params[0] {
|
||||
variables[k] = v
|
||||
}
|
||||
for k, v := range view.data {
|
||||
variables[k] = v
|
||||
}
|
||||
} else {
|
||||
variables = view.data
|
||||
}
|
||||
} else {
|
||||
if len(params) > 0 {
|
||||
variables = params[0]
|
||||
}
|
||||
gutil.MapMerge(variables, view.data)
|
||||
}
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if view.config.AutoEncode {
|
||||
@ -249,14 +210,20 @@ func (view *View) ParseContent(content string, params ...Params) (string, error)
|
||||
// if the template files under <path> changes (recursively).
|
||||
func (view *View) getTemplate(filePath, folderPath, pattern string) (tpl interface{}, err error) {
|
||||
// Key for template cache.
|
||||
key := fmt.Sprintf("%s_%v", filePath, view.delimiters)
|
||||
key := fmt.Sprintf("%s_%v", filePath, view.config.Delimiters)
|
||||
result := templates.GetOrSetFuncLock(key, func() interface{} {
|
||||
// Do not use <key> but the <filePath> as the parameter <name> for function New,
|
||||
// because when error occurs the <name> will be printed out for error locating.
|
||||
if view.config.AutoEncode {
|
||||
tpl = htmltpl.New(filePath).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcMap)
|
||||
tpl = htmltpl.New(filePath).Delims(
|
||||
view.config.Delimiters[0],
|
||||
view.config.Delimiters[1],
|
||||
).Funcs(view.funcMap)
|
||||
} else {
|
||||
tpl = texttpl.New(filePath).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcMap)
|
||||
tpl = texttpl.New(filePath).Delims(
|
||||
view.config.Delimiters[0],
|
||||
view.config.Delimiters[1],
|
||||
).Funcs(view.funcMap)
|
||||
}
|
||||
// Firstly checking the resource manager.
|
||||
if !gres.IsEmpty() {
|
||||
|
||||
@ -8,12 +8,6 @@ package gutil
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/internal/utils"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var (
|
||||
// replaceCharReg is the regular expression object for replacing chars in map keys.
|
||||
replaceCharReg, _ = regexp.Compile(`[\-\.\_\s]+`)
|
||||
)
|
||||
|
||||
// MapCopy does a shallow copy from map <data> to <copy> for most commonly used map type
|
||||
@ -32,6 +26,29 @@ func MapContains(data map[string]interface{}, key string) (ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// MapMerge merges all map from <src> to map <dst>.
|
||||
func MapMerge(dst map[string]interface{}, src ...map[string]interface{}) {
|
||||
if dst == nil {
|
||||
return
|
||||
}
|
||||
for _, m := range src {
|
||||
for k, v := range m {
|
||||
dst[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MapMergeCopy creates and returns a new map which merges all map from <src>.
|
||||
func MapMergeCopy(src ...map[string]interface{}) (copy map[string]interface{}) {
|
||||
copy = make(map[string]interface{})
|
||||
for _, m := range src {
|
||||
for k, v := range m {
|
||||
copy[k] = v
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MapPossibleItemByKey tries to find the possible key-value pair for given key with or without
|
||||
// cases or chars '-'/'_'/'.'/' '.
|
||||
//
|
||||
|
||||
@ -12,6 +12,15 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
m1 = map[string]interface{}{
|
||||
"k1": "v1",
|
||||
}
|
||||
m2 = map[string]interface{}{
|
||||
"k2": "v2",
|
||||
}
|
||||
)
|
||||
|
||||
func Benchmark_TryCatch(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
TryCatch(func() {
|
||||
@ -21,3 +30,9 @@ func Benchmark_TryCatch(b *testing.B) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_MapMergeCopy(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
MapMergeCopy(m1, m2)
|
||||
}
|
||||
}
|
||||
|
||||
120
util/gutil/gutil_z_unit_map_test.go
Executable file
120
util/gutil/gutil_z_unit_map_test.go
Executable file
@ -0,0 +1,120 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/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://github.com/gogf/gf.
|
||||
|
||||
package gutil_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
)
|
||||
|
||||
func Test_MapCopy(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m1 := g.Map{
|
||||
"k1": "v1",
|
||||
}
|
||||
m2 := gutil.MapCopy(m1)
|
||||
m2["k2"] = "v2"
|
||||
|
||||
t.Assert(m1["k1"], "v1")
|
||||
t.Assert(m1["k2"], nil)
|
||||
t.Assert(m2["k1"], "v1")
|
||||
t.Assert(m2["k2"], "v2")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapContains(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m1 := g.Map{
|
||||
"k1": "v1",
|
||||
}
|
||||
t.Assert(gutil.MapContains(m1, "k1"), true)
|
||||
t.Assert(gutil.MapContains(m1, "K1"), false)
|
||||
t.Assert(gutil.MapContains(m1, "k2"), false)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapMerge(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m1 := g.Map{
|
||||
"k1": "v1",
|
||||
}
|
||||
m2 := g.Map{
|
||||
"k2": "v2",
|
||||
}
|
||||
m3 := g.Map{
|
||||
"k3": "v3",
|
||||
}
|
||||
gutil.MapMerge(m1, m2, m3, nil)
|
||||
t.Assert(m1["k1"], "v1")
|
||||
t.Assert(m1["k2"], "v2")
|
||||
t.Assert(m1["k3"], "v3")
|
||||
t.Assert(m2["k1"], nil)
|
||||
t.Assert(m3["k1"], nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapMergeCopy(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m1 := g.Map{
|
||||
"k1": "v1",
|
||||
}
|
||||
m2 := g.Map{
|
||||
"k2": "v2",
|
||||
}
|
||||
m3 := g.Map{
|
||||
"k3": "v3",
|
||||
}
|
||||
m := gutil.MapMergeCopy(m1, m2, m3, nil)
|
||||
t.Assert(m["k1"], "v1")
|
||||
t.Assert(m["k2"], "v2")
|
||||
t.Assert(m["k3"], "v3")
|
||||
t.Assert(m1["k1"], "v1")
|
||||
t.Assert(m1["k2"], nil)
|
||||
t.Assert(m2["k1"], nil)
|
||||
t.Assert(m3["k1"], nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapPossibleItemByKey(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := g.Map{
|
||||
"name": "guo",
|
||||
"NickName": "john",
|
||||
}
|
||||
k, v := gutil.MapPossibleItemByKey(m, "NAME")
|
||||
t.Assert(k, "name")
|
||||
t.Assert(v, "guo")
|
||||
|
||||
k, v = gutil.MapPossibleItemByKey(m, "nick name")
|
||||
t.Assert(k, "NickName")
|
||||
t.Assert(v, "john")
|
||||
|
||||
k, v = gutil.MapPossibleItemByKey(m, "none")
|
||||
t.Assert(k, "")
|
||||
t.Assert(v, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_MapContainsPossibleKey(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := g.Map{
|
||||
"name": "guo",
|
||||
"NickName": "john",
|
||||
}
|
||||
t.Assert(gutil.MapContainsPossibleKey(m, "name"), true)
|
||||
t.Assert(gutil.MapContainsPossibleKey(m, "NAME"), true)
|
||||
t.Assert(gutil.MapContainsPossibleKey(m, "nickname"), true)
|
||||
t.Assert(gutil.MapContainsPossibleKey(m, "nick name"), true)
|
||||
t.Assert(gutil.MapContainsPossibleKey(m, "nick_name"), true)
|
||||
t.Assert(gutil.MapContainsPossibleKey(m, "nick-name"), true)
|
||||
t.Assert(gutil.MapContainsPossibleKey(m, "nick.name"), true)
|
||||
t.Assert(gutil.MapContainsPossibleKey(m, "none"), false)
|
||||
})
|
||||
}
|
||||
@ -19,18 +19,9 @@ func Test_Dump(t *testing.T) {
|
||||
100: 100,
|
||||
})
|
||||
})
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
gutil.Dump(map[string]interface{}{"": func() {}})
|
||||
})
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
gutil.Dump([]byte("gutil Dump test"))
|
||||
})
|
||||
}
|
||||
|
||||
func Test_TryCatch(t *testing.T) {
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
gutil.TryCatch(func() {
|
||||
panic("gutil TryCatch test")
|
||||
|
||||
Reference in New Issue
Block a user