add context for intlog/gsession;improve struct/structs converting for package gconv

This commit is contained in:
John Guo
2021-06-26 16:23:54 +08:00
parent c25f88293b
commit 50ffaef33f
58 changed files with 517 additions and 421 deletions

View File

@ -486,14 +486,16 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
// Cache the underlying connection pool object by node.
v, _ := internalCache.GetOrSetFuncLock(node.String(), func() (interface{}, error) {
intlog.Printf(
c.db.GetCtx(),
`open new connection, master:%#v, config:%#v, node:%#v`,
master, c.config, node,
)
defer func() {
if err != nil {
intlog.Printf(`open new connection failed: %v, %#v`, err, node)
intlog.Printf(c.db.GetCtx(), `open new connection failed: %v, %#v`, err, node)
} else {
intlog.Printf(
c.db.GetCtx(),
`open new connection success, master:%#v, config:%#v, node:%#v`,
master, c.config, node,
)

View File

@ -50,7 +50,7 @@ func (d *DriverMssql) Open(config *ConfigNode) (*sql.DB, error) {
config.User, config.Pass, config.Host, config.Port, config.Name,
)
}
intlog.Printf("Open: %s", source)
intlog.Printf(d.GetCtx(), "Open: %s", source)
if db, err := sql.Open("sqlserver", source); err == nil {
return db, nil
} else {

View File

@ -52,7 +52,7 @@ func (d *DriverMysql) Open(config *ConfigNode) (*sql.DB, error) {
source = fmt.Sprintf("%s&loc=%s", source, url.QueryEscape(config.Timezone))
}
}
intlog.Printf("Open: %s", source)
intlog.Printf(d.GetCtx(), "Open: %s", source)
if db, err := sql.Open("mysql", source); err == nil {
return db, nil
} else {

View File

@ -56,7 +56,7 @@ func (d *DriverOracle) Open(config *ConfigNode) (*sql.DB, error) {
config.User, config.Pass, config.Host, config.Port, config.Name,
)
}
intlog.Printf("Open: %s", source)
intlog.Printf(d.GetCtx(), "Open: %s", source)
if db, err := sql.Open("oci8", source); err == nil {
return db, nil
} else {

View File

@ -51,7 +51,7 @@ func (d *DriverPgsql) Open(config *ConfigNode) (*sql.DB, error) {
source = fmt.Sprintf("%s timezone=%s", source, config.Timezone)
}
}
intlog.Printf("Open: %s", source)
intlog.Printf(d.GetCtx(), "Open: %s", source)
if db, err := sql.Open("postgres", source); err == nil {
return db, nil
} else {

View File

@ -47,7 +47,7 @@ func (d *DriverSqlite) Open(config *ConfigNode) (*sql.DB, error) {
if absolutePath, _ := gfile.Search(source); absolutePath != "" {
source = absolutePath
}
intlog.Printf("Open: %s", source)
intlog.Printf(d.GetCtx(), "Open: %s", source)
if db, err := sql.Open("sqlite3", source); err == nil {
return db, nil
} else {

View File

@ -546,11 +546,11 @@ func (m *Model) doGetAllBySql(sql string, args ...interface{}) (result Result, e
if cacheKey != "" && err == nil {
if m.cacheDuration < 0 {
if _, err := cacheObj.Remove(cacheKey); err != nil {
intlog.Error(err)
intlog.Error(m.GetCtx(), err)
}
} else {
if err := cacheObj.Set(cacheKey, result, m.cacheDuration); err != nil {
intlog.Error(err)
intlog.Error(m.GetCtx(), err)
}
}
}

View File

@ -52,7 +52,7 @@ func (r Record) Struct(pointer interface{}) error {
}
return nil
}
return gconv.StructTag(r.Map(), pointer, OrmTagForStruct)
return gconv.StructTag(r, pointer, OrmTagForStruct)
}
// IsEmpty checks and returns whether `r` is empty.

View File

@ -189,5 +189,5 @@ func (r Result) RecordKeyUint(key string) map[uint]Record {
// Structs converts `r` to struct slice.
// Note that the parameter `pointer` should be type of *[]struct/*[]*struct.
func (r Result) Structs(pointer interface{}) (err error) {
return gconv.StructsTag(r.List(), pointer, OrmTagForStruct)
return gconv.StructsTag(r, pointer, OrmTagForStruct)
}

View File

@ -8,10 +8,13 @@ package gdb_test
import (
"database/sql"
"github.com/gogf/gf/database/gdb"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gtime"
"github.com/gogf/gf/test/gtest"
"github.com/gogf/gf/util/gconv"
"reflect"
"testing"
)
@ -395,17 +398,17 @@ type User struct {
}
func (user *User) UnmarshalValue(value interface{}) error {
switch result := value.(type) {
case map[string]interface{}:
user.Id = result["id"].(int)
user.Passport = result["passport"].(string)
user.Password = ""
user.Nickname = result["nickname"].(string)
user.CreateTime = gtime.New(result["create_time"])
if record, ok := value.(gdb.Record); ok {
*user = User{
Id: record["id"].Int(),
Passport: record["passport"].String(),
Password: "",
Nickname: record["nickname"].String(),
CreateTime: record["create_time"].GTime(),
}
return nil
default:
return gconv.Struct(value, user)
}
return gerror.Newf(`unsupported value type for UnmarshalValue: %v`, reflect.TypeOf(value))
}
func Test_Model_Scan_UnmarshalValue(t *testing.T) {

View File

@ -114,7 +114,7 @@ func New(config *Config) *Redis {
if err != nil {
return nil, err
}
intlog.Printf(`open new connection, config:%+v`, config)
intlog.Printf(context.TODO(), `open new connection, config:%+v`, config)
// AUTH
if len(config.Pass) > 0 {
if _, err := c.Do("AUTH", config.Pass); err != nil {

View File

@ -7,6 +7,7 @@
package gredis
import (
"context"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/intlog"
@ -36,7 +37,7 @@ func SetConfig(config *Config, name ...string) {
configs.Set(group, config)
instances.Remove(group)
intlog.Printf(`SetConfig for group "%s": %+v`, group, config)
intlog.Printf(context.TODO(), `SetConfig for group "%s": %+v`, group, config)
}
// SetConfigByStr sets the global configuration for specified group with string.
@ -78,7 +79,7 @@ func RemoveConfig(name ...string) {
configs.Remove(group)
instances.Remove(group)
intlog.Printf(`RemoveConfig: %s`, group)
intlog.Printf(context.TODO(), `RemoveConfig: %s`, group)
}
// ConfigFromStr parses and returns config from given str.

View File

@ -9,6 +9,7 @@ package gcompress
import (
"archive/zip"
"bytes"
"context"
"github.com/gogf/gf/internal/intlog"
"github.com/gogf/gf/os/gfile"
"github.com/gogf/gf/text/gstr"
@ -92,7 +93,7 @@ func doZipPathWriter(path string, exclude string, zipWriter *zip.Writer, prefix
headerPrefix = strings.Replace(headerPrefix, "//", "/", -1)
for _, file := range files {
if exclude == file {
intlog.Printf(`exclude file path: %s`, file)
intlog.Printf(context.TODO(), `exclude file path: %s`, file)
continue
}
dir := gfile.Dir(file[len(path):])

View File

@ -7,6 +7,7 @@
package gins
import (
"context"
"fmt"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/intlog"
@ -92,11 +93,11 @@ func Database(name ...string) gdb.DB {
}
if len(cg) > 0 {
if gdb.GetConfig(group) == nil {
intlog.Printf("add configuration for group: %s, %#v", g, cg)
intlog.Printf(context.TODO(), "add configuration for group: %s, %#v", g, cg)
gdb.SetConfigGroup(g, cg)
} else {
intlog.Printf("ignore configuration as it already exists for group: %s, %#v", g, cg)
intlog.Printf("%s, %#v", g, cg)
intlog.Printf(context.TODO(), "ignore configuration as it already exists for group: %s, %#v", g, cg)
intlog.Printf(context.TODO(), "%s, %#v", g, cg)
}
}
}
@ -110,11 +111,11 @@ func Database(name ...string) gdb.DB {
if len(cg) > 0 {
if gdb.GetConfig(group) == nil {
intlog.Printf("add configuration for group: %s, %#v", gdb.DefaultGroupName, cg)
intlog.Printf(context.TODO(), "add configuration for group: %s, %#v", gdb.DefaultGroupName, cg)
gdb.SetConfigGroup(gdb.DefaultGroupName, cg)
} else {
intlog.Printf("ignore configuration as it already exists for group: %s, %#v", gdb.DefaultGroupName, cg)
intlog.Printf("%s, %#v", gdb.DefaultGroupName, cg)
intlog.Printf(context.TODO(), "ignore configuration as it already exists for group: %s, %#v", gdb.DefaultGroupName, cg)
intlog.Printf(context.TODO(), "%s, %#v", gdb.DefaultGroupName, cg)
}
}
}

View File

@ -70,7 +70,7 @@ func New(options ...Options) *Manager {
gregex.Quote(opts.Delimiters[1]),
),
}
intlog.Printf(`New: %#v`, m)
intlog.Printf(context.TODO(), `New: %#v`, m)
return m
}
@ -105,20 +105,20 @@ func (m *Manager) SetPath(path string) error {
}
m.options.Path = realPath
}
intlog.Printf(`SetPath: %s`, m.options.Path)
intlog.Printf(context.TODO(), `SetPath: %s`, m.options.Path)
return nil
}
// SetLanguage sets the language for translator.
func (m *Manager) SetLanguage(language string) {
m.options.Language = language
intlog.Printf(`SetLanguage: %s`, m.options.Language)
intlog.Printf(context.TODO(), `SetLanguage: %s`, m.options.Language)
}
// SetDelimiters sets the delimiters for translator.
func (m *Manager) SetDelimiters(left, right string) {
m.pattern = fmt.Sprintf(`%s(\w+)%s`, gregex.Quote(left), gregex.Quote(right))
intlog.Printf(`SetDelimiters: %v`, m.pattern)
intlog.Printf(context.TODO(), `SetDelimiters: %v`, m.pattern)
}
// T is alias of Translate for convenience.
@ -139,7 +139,7 @@ func (m *Manager) TranslateFormat(ctx context.Context, format string, values ...
// Translate translates <content> with configured language.
func (m *Manager) Translate(ctx context.Context, content string) string {
m.init()
m.init(ctx)
m.mu.RLock()
defer m.mu.RUnlock()
transLang := m.options.Language
@ -163,14 +163,14 @@ func (m *Manager) Translate(ctx context.Context, content string) string {
}
return match[0]
})
intlog.Printf(`Translate for language: %s`, transLang)
intlog.Printf(ctx, `Translate for language: %s`, transLang)
return result
}
// GetContent retrieves and returns the configured content for given key and specified language.
// It returns an empty string if not found.
func (m *Manager) GetContent(ctx context.Context, key string) string {
m.init()
m.init(ctx)
m.mu.RLock()
defer m.mu.RUnlock()
transLang := m.options.Language
@ -185,7 +185,7 @@ func (m *Manager) GetContent(ctx context.Context, key string) string {
// init initializes the manager for lazy initialization design.
// The i18n manager is only initialized once.
func (m *Manager) init() {
func (m *Manager) init(ctx context.Context) {
m.mu.RLock()
// If the data is not nil, means it's already initialized.
if m.data != nil {
@ -223,17 +223,13 @@ func (m *Manager) init() {
m.data[lang][k] = gconv.String(v)
}
} else {
intlog.Errorf("load i18n file '%s' failed: %v", name, err)
intlog.Errorf(ctx, "load i18n file '%s' failed: %v", name, err)
}
}
}
} else if m.options.Path != "" {
files, _ := gfile.ScanDirFile(m.options.Path, "*.*", true)
if len(files) == 0 {
//intlog.Printf(
// "no i18n files found in configured directory: %s",
// m.options.Path,
//)
return
}
var (
@ -258,7 +254,7 @@ func (m *Manager) init() {
m.data[lang][k] = gconv.String(v)
}
} else {
intlog.Errorf("load i18n file '%s' failed: %v", file, err)
intlog.Errorf(ctx, "load i18n file '%s' failed: %v", file, err)
}
}
// Monitor changes of i18n files for hot reload feature.

View File

@ -8,9 +8,12 @@
package intlog
import (
"bytes"
"context"
"fmt"
"github.com/gogf/gf/debug/gdebug"
"github.com/gogf/gf/internal/utils"
"go.opentelemetry.io/otel/trace"
"path/filepath"
"time"
)
@ -39,42 +42,56 @@ func SetEnabled(enabled bool) {
// Print prints `v` with newline using fmt.Println.
// The parameter `v` can be multiple variables.
func Print(v ...interface{}) {
if !isGFDebug {
return
}
fmt.Println(append([]interface{}{now(), "[INTE]", file()}, v...)...)
func Print(ctx context.Context, v ...interface{}) {
doPrint(ctx, fmt.Sprint(v...), false)
}
// Printf prints `v` with format `format` using fmt.Printf.
// The parameter `v` can be multiple variables.
func Printf(format string, v ...interface{}) {
if !isGFDebug {
return
}
fmt.Printf(now()+" [INTE] "+file()+" "+format+"\n", v...)
func Printf(ctx context.Context, format string, v ...interface{}) {
doPrint(ctx, fmt.Sprintf(format, v...), false)
}
// Error prints `v` with newline using fmt.Println.
// The parameter `v` can be multiple variables.
func Error(v ...interface{}) {
if !isGFDebug {
return
}
array := append([]interface{}{now(), "[INTE]", file()}, v...)
array = append(array, "\n"+gdebug.StackWithFilter(stackFilterKey))
fmt.Println(array...)
func Error(ctx context.Context, v ...interface{}) {
doPrint(ctx, fmt.Sprint(v...), true)
}
// Errorf prints `v` with format `format` using fmt.Printf.
func Errorf(format string, v ...interface{}) {
func Errorf(ctx context.Context, format string, v ...interface{}) {
doPrint(ctx, fmt.Sprintf(format, v...), true)
}
func doPrint(ctx context.Context, content string, stack bool) {
if !isGFDebug {
return
}
fmt.Printf(
now()+" [INTE] "+file()+" "+format+"\n%s\n",
append(v, gdebug.StackWithFilter(stackFilterKey))...,
)
buffer := bytes.NewBuffer(nil)
buffer.WriteString(now())
buffer.WriteString(" [INTE] ")
buffer.WriteString(file())
if s := traceIdStr(ctx); s != "" {
buffer.WriteString(" " + s)
}
buffer.WriteString(content)
buffer.WriteString("\n")
if stack {
buffer.WriteString(gdebug.StackWithFilter(stackFilterKey))
}
fmt.Print(buffer.String())
}
// traceIdStr retrieves and returns the trace id string for logging output.
func traceIdStr(ctx context.Context) string {
if ctx == nil {
return ""
}
spanCtx := trace.SpanContextFromContext(ctx)
if traceId := spanCtx.TraceID(); traceId.IsValid() {
return "{" + traceId.String() + "}"
}
return ""
}
// now returns current time string.

View File

@ -73,7 +73,10 @@ func newRequest(s *Server, r *http.Request, w http.ResponseWriter) *Request {
EnterTime: gtime.TimestampMilli(),
}
request.Cookie = GetCookie(request)
request.Session = s.sessionManager.New(request.GetSessionId())
request.Session = s.sessionManager.New(
r.Context(),
request.GetSessionId(),
)
request.Response.Request = request
request.Middleware = &middleware{
request: request,
@ -84,7 +87,7 @@ func newRequest(s *Server, r *http.Request, w http.ResponseWriter) *Request {
address = request.RemoteAddr
header = fmt.Sprintf("%v", request.Header)
)
intlog.Print(address, header)
intlog.Print(r.Context(), address, header)
return guid.S([]byte(address), []byte(header))
})
if err != nil {

View File

@ -7,7 +7,9 @@
package ghttp
import (
"context"
"errors"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/intlog"
"github.com/gogf/gf/os/gfile"
"github.com/gogf/gf/os/gtime"
@ -21,6 +23,7 @@ import (
// UploadFile wraps the multipart uploading file with more and convenient features.
type UploadFile struct {
*multipart.FileHeader
ctx context.Context
}
// UploadFiles is array type for *UploadFile.
@ -40,7 +43,7 @@ func (f *UploadFile) Save(dirPath string, randomlyRename ...bool) (filename stri
return
}
} else if !gfile.IsDir(dirPath) {
return "", errors.New(`parameter "dirPath" should be a directory path`)
return "", gerror.New(`parameter "dirPath" should be a directory path`)
}
file, err := f.Open()
@ -60,7 +63,7 @@ func (f *UploadFile) Save(dirPath string, randomlyRename ...bool) (filename stri
return "", err
}
defer newFile.Close()
intlog.Printf(`save upload file: %s`, filePath)
intlog.Printf(f.ctx, `save upload file: %s`, filePath)
if _, err := io.Copy(newFile, file); err != nil {
return "", err
}
@ -114,6 +117,7 @@ func (r *Request) GetUploadFiles(name string) UploadFiles {
uploadFiles := make(UploadFiles, len(multipartFiles))
for k, v := range multipartFiles {
uploadFiles[k] = &UploadFile{
ctx: r.Context(),
FileHeader: v,
}
}

View File

@ -8,6 +8,7 @@ package ghttp
import (
"bytes"
"context"
"github.com/gogf/gf/debug/gdebug"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/intlog"
@ -70,10 +71,10 @@ func serverProcessInit() {
// Process message handler.
// It's enabled only graceful feature is enabled.
if gracefulEnabled {
intlog.Printf("%d: graceful reload feature is enabled", gproc.Pid())
intlog.Printf(context.TODO(), "%d: graceful reload feature is enabled", gproc.Pid())
go handleProcessMessage()
} else {
intlog.Printf("%d: graceful reload feature is disabled", gproc.Pid())
intlog.Printf(context.TODO(), "%d: graceful reload feature is disabled", gproc.Pid())
}
// It's an ugly calling for better initializing the main package path
@ -195,7 +196,7 @@ func (s *Server) Start() error {
if gproc.IsChild() {
gtimer.SetTimeout(time.Duration(s.config.GracefulTimeout)*time.Second, func() {
if err := gproc.Send(gproc.PPid(), []byte("exit"), adminGProcCommGroup); err != nil {
intlog.Error("server error in process communication:", err)
intlog.Error(context.TODO(), "server error in process communication:", err)
}
})
}
@ -315,9 +316,9 @@ func (s *Server) Run() {
// Remove plugins.
if len(s.plugins) > 0 {
for _, p := range s.plugins {
intlog.Printf(`remove plugin: %s`, p.Name())
intlog.Printf(context.TODO(), `remove plugin: %s`, p.Name())
if err := p.Remove(); err != nil {
intlog.Errorf("%+v", err)
intlog.Errorf(context.TODO(), "%+v", err)
}
}
}
@ -333,7 +334,7 @@ func Wait() {
s := v.(*Server)
if len(s.plugins) > 0 {
for _, p := range s.plugins {
intlog.Printf(`remove plugin: %s`, p.Name())
intlog.Printf(context.TODO(), `remove plugin: %s`, p.Name())
p.Remove()
}
}

View File

@ -8,6 +8,7 @@ package ghttp
import (
"bytes"
"context"
"errors"
"fmt"
"github.com/gogf/gf/internal/intlog"
@ -266,10 +267,10 @@ func handleProcessMessage() {
for {
if msg := gproc.Receive(adminGProcCommGroup); msg != nil {
if bytes.EqualFold(msg.Data, []byte("exit")) {
intlog.Printf("%d: process message: exit", gproc.Pid())
intlog.Printf(context.TODO(), "%d: process message: exit", gproc.Pid())
shutdownWebServersGracefully()
allDoneChan <- struct{}{}
intlog.Printf("%d: process message: exit done", gproc.Pid())
intlog.Printf(context.TODO(), "%d: process message: exit done", gproc.Pid())
return
}
}

View File

@ -9,6 +9,7 @@
package ghttp
import (
"context"
"github.com/gogf/gf/internal/intlog"
"os"
"os/signal"
@ -33,7 +34,7 @@ func handleProcessSignal() {
)
for {
sig = <-procSignalChan
intlog.Printf(`signal received: %s`, sig.String())
intlog.Printf(context.TODO(), `signal received: %s`, sig.String())
switch sig {
// Shutdown the servers.
case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGABRT:
@ -49,7 +50,7 @@ func handleProcessSignal() {
// Restart the servers.
case syscall.SIGUSR1:
if err := restartWebServers(sig.String()); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
return

View File

@ -7,6 +7,7 @@
package ghttp
import (
"context"
"crypto/tls"
"fmt"
"github.com/gogf/gf/internal/intlog"
@ -333,11 +334,11 @@ func (s *Server) SetConfig(c ServerConfig) error {
}
}
if err := s.config.Logger.SetLevelStr(s.config.LogLevel); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
SetGraceful(c.Graceful)
intlog.Printf("SetConfig: %+v", s.config)
intlog.Printf(context.TODO(), "SetConfig: %+v", s.config)
return nil
}

View File

@ -83,12 +83,12 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// to release the file descriptor in time.
err := request.Request.Body.Close()
if err != nil {
intlog.Error(err)
intlog.Error(request.Context(), err)
}
if request.Request.Response != nil {
err = request.Request.Response.Body.Close()
if err != nil {
intlog.Error(err)
intlog.Error(request.Context(), err)
}
}
}()

View File

@ -195,12 +195,12 @@ func (c *Client) prepareRequest(method, url string, data ...interface{}) (req *h
if f, err := os.Open(path); err == nil {
if _, err = io.Copy(file, f); err != nil {
if err := f.Close(); err != nil {
intlog.Errorf(`%+v`, err)
intlog.Errorf(c.ctx, `%+v`, err)
}
return nil, err
}
if err := f.Close(); err != nil {
intlog.Errorf(`%+v`, err)
intlog.Errorf(c.ctx, `%+v`, err)
}
} else {
return nil, err
@ -303,7 +303,7 @@ func (c *Client) callRequest(req *http.Request) (resp *Response, err error) {
// The response might not be nil when err != nil.
if resp.Response != nil {
if err := resp.Response.Body.Close(); err != nil {
intlog.Errorf(`%+v`, err)
intlog.Errorf(c.ctx, `%+v`, err)
}
}
if c.retryCount > 0 {

View File

@ -8,6 +8,7 @@
package gcfg
import (
"context"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/container/gmap"
"github.com/gogf/gf/internal/intlog"
@ -82,7 +83,7 @@ func RemoveContent(file ...string) {
}
})
intlog.Printf(`RemoveContent: %s`, name)
intlog.Printf(context.TODO(), `RemoveContent: %s`, name)
}
// ClearContent removes all global configuration contents.
@ -95,7 +96,7 @@ func ClearContent() {
}
})
intlog.Print(`RemoveConfig`)
intlog.Print(context.TODO(), `RemoveConfig`)
}
// errorPrint checks whether printing error to stdout.

View File

@ -8,6 +8,7 @@ package gcfg
import (
"bytes"
"context"
"errors"
"fmt"
"github.com/gogf/gf/container/garray"
@ -54,20 +55,20 @@ func New(file ...string) *Config {
} else {
// Dir path of working dir.
if err := c.AddPath(gfile.Pwd()); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
// Dir path of main package.
if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) {
if err := c.AddPath(mainPath); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
}
// Dir path of binary.
if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) {
if err := c.AddPath(selfPath); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
}
}
@ -163,7 +164,7 @@ func (c *Config) SetPath(path string) error {
c.jsonMap.Clear()
c.searchPaths.Clear()
c.searchPaths.Append(realPath)
intlog.Print("SetPath:", realPath)
intlog.Print(context.TODO(), "SetPath:", realPath)
return nil
}
@ -237,7 +238,7 @@ func (c *Config) AddPath(path string) error {
return nil
}
c.searchPaths.Append(realPath)
intlog.Print("AddPath:", realPath)
intlog.Print(context.TODO(), "AddPath:", realPath)
return nil
}

View File

@ -8,6 +8,7 @@
package gfsnotify
import (
"context"
"errors"
"fmt"
"github.com/gogf/gf/container/gset"
@ -88,7 +89,7 @@ func New() (*Watcher, error) {
if watcher, err := fsnotify.NewWatcher(); err == nil {
w.watcher = watcher
} else {
intlog.Printf("New watcher failed: %v", err)
intlog.Printf(context.TODO(), "New watcher failed: %v", err)
return nil, err
}
w.watchLoop()

View File

@ -7,6 +7,7 @@
package gfsnotify
import (
"context"
"errors"
"fmt"
"github.com/gogf/gf/internal/intlog"
@ -45,9 +46,9 @@ func (w *Watcher) AddOnce(name, path string, callbackFunc func(event *Event), re
for _, subPath := range fileAllDirs(path) {
if fileIsDir(subPath) {
if err := w.watcher.Add(subPath); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
} else {
intlog.Printf("watcher adds monitor for: %s", subPath)
intlog.Printf(context.TODO(), "watcher adds monitor for: %s", subPath)
}
}
}
@ -93,9 +94,9 @@ func (w *Watcher) addWithCallbackFunc(name, path string, callbackFunc func(event
})
// Add the path to underlying monitor.
if err := w.watcher.Add(path); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
} else {
intlog.Printf("watcher adds monitor for: %s", path)
intlog.Printf(context.TODO(), "watcher adds monitor for: %s", path)
}
// Add the callback to global callback map.
callbackIdMap.Set(callback.Id, callback)
@ -108,7 +109,7 @@ func (w *Watcher) addWithCallbackFunc(name, path string, callbackFunc func(event
func (w *Watcher) Close() {
w.events.Close()
if err := w.watcher.Close(); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
close(w.closeChan)
}
@ -131,7 +132,7 @@ func (w *Watcher) Remove(path string) error {
for _, subPath := range subPaths {
if w.checkPathCanBeRemoved(subPath) {
if err := w.watcher.Remove(subPath); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
}
}

View File

@ -7,6 +7,7 @@
package gfsnotify
import (
"context"
"github.com/gogf/gf/container/glist"
"github.com/gogf/gf/internal/intlog"
)
@ -34,7 +35,7 @@ func (w *Watcher) watchLoop() {
}, repeatEventFilterDuration)
case err := <-w.watcher.Errors:
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
}
}()
@ -60,9 +61,9 @@ func (w *Watcher) eventLoop() {
// It adds the path back to monitor.
// We need no worry about the repeat adding.
if err := w.watcher.Add(event.Path); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
} else {
intlog.Printf("fake remove event, watcher re-adds monitor for: %s", event.Path)
intlog.Printf(context.TODO(), "fake remove event, watcher re-adds monitor for: %s", event.Path)
}
// Change the event to RENAME, which means it renames itself to its origin name.
event.Op = RENAME
@ -76,9 +77,9 @@ func (w *Watcher) eventLoop() {
// It might lost the monitoring for the path, so we add the path back to monitor.
// We need no worry about the repeat adding.
if err := w.watcher.Add(event.Path); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
} else {
intlog.Printf("fake rename event, watcher re-adds monitor for: %s", event.Path)
intlog.Printf(context.TODO(), "fake rename event, watcher re-adds monitor for: %s", event.Path)
}
// Change the event to CHMOD.
event.Op = CHMOD
@ -94,18 +95,18 @@ func (w *Watcher) eventLoop() {
for _, subPath := range fileAllDirs(event.Path) {
if fileIsDir(subPath) {
if err := w.watcher.Add(subPath); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
} else {
intlog.Printf("folder creation event, watcher adds monitor for: %s", subPath)
intlog.Printf(context.TODO(), "folder creation event, watcher adds monitor for: %s", subPath)
}
}
}
} else {
// If it's a file, it directly adds it to monitor.
if err := w.watcher.Add(event.Path); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
} else {
intlog.Printf("file creation event, watcher adds monitor for: %s", event.Path)
intlog.Printf(context.TODO(), "file creation event, watcher adds monitor for: %s", event.Path)
}
}

View File

@ -38,11 +38,12 @@ type Logger struct {
}
const (
defaultFileFormat = `{Y-m-d}.log`
defaultFileFlags = os.O_CREATE | os.O_WRONLY | os.O_APPEND
defaultFilePerm = os.FileMode(0666)
defaultFileExpire = time.Minute
pathFilterKey = "/os/glog/glog"
defaultFileFormat = `{Y-m-d}.log`
defaultFileFlags = os.O_CREATE | os.O_WRONLY | os.O_APPEND
defaultFilePerm = os.FileMode(0666)
defaultFileExpire = time.Minute
pathFilterKey = "/os/glog/glog"
memoryLockPrefixForPrintingToFile = "glog.printToFile:"
)
const (
@ -106,7 +107,7 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
if p.config.RotateSize > 0 || p.config.RotateExpire > 0 {
if !p.init.Val() && p.init.Cas(false, true) {
gtimer.AddOnce(p.config.RotateCheckInterval, p.rotateChecksTimely)
intlog.Printf("logger rotation initialized: every %s", p.config.RotateCheckInterval.String())
intlog.Printf(ctx, "logger rotation initialized: every %s", p.config.RotateCheckInterval.String())
}
}
@ -168,7 +169,7 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
// Tracing values.
spanCtx := trace.SpanContextFromContext(ctx)
if traceId := spanCtx.TraceID(); traceId.IsValid() {
input.CtxStr = "{TraceID:" + traceId.String() + "}"
input.CtxStr = "{" + traceId.String() + "}"
}
// Context values.
if len(l.config.CtxKeys) > 0 {
@ -210,7 +211,7 @@ func (l *Logger) print(ctx context.Context, level int, values ...interface{}) {
input.Next()
})
if err != nil {
intlog.Error(err)
intlog.Error(ctx, err)
}
} else {
input.Next()
@ -223,27 +224,26 @@ func (l *Logger) printToWriter(ctx context.Context, input *HandlerInput) {
if l.config.Writer == nil {
// Output content to disk file.
if l.config.Path != "" {
l.printToFile(input.Time, buffer)
l.printToFile(ctx, input.Time, buffer)
}
// Allow output to stdout?
if l.config.StdoutPrint {
if _, err := os.Stdout.Write(buffer.Bytes()); err != nil {
intlog.Error(err)
intlog.Error(ctx, err)
}
}
} else {
if _, err := l.config.Writer.Write(buffer.Bytes()); err != nil {
// panic(err)
intlog.Error(err)
intlog.Error(ctx, err)
}
}
}
// printToFile outputs logging content to disk file.
func (l *Logger) printToFile(t time.Time, buffer *bytes.Buffer) {
func (l *Logger) printToFile(ctx context.Context, t time.Time, buffer *bytes.Buffer) {
var (
logFilePath = l.getFilePath(t)
memoryLockKey = "glog.printToFile:" + logFilePath
memoryLockKey = memoryLockPrefixForPrintingToFile + logFilePath
)
gmlock.Lock(memoryLockKey)
defer gmlock.Unlock(memoryLockKey)
@ -255,20 +255,20 @@ func (l *Logger) printToFile(t time.Time, buffer *bytes.Buffer) {
}
}
// Logging content outputting to disk file.
if file := l.getFilePointer(logFilePath); file == nil {
intlog.Errorf(`got nil file pointer for: %s`, logFilePath)
if file := l.getFilePointer(ctx, logFilePath); file == nil {
intlog.Errorf(ctx, `got nil file pointer for: %s`, logFilePath)
} else {
if _, err := file.Write(buffer.Bytes()); err != nil {
intlog.Error(err)
intlog.Error(ctx, err)
}
if err := file.Close(); err != nil {
intlog.Error(err)
intlog.Error(ctx, err)
}
}
}
// getFilePointer retrieves and returns a file pointer from file pool.
func (l *Logger) getFilePointer(path string) *gfpool.File {
func (l *Logger) getFilePointer(ctx context.Context, path string) *gfpool.File {
file, err := gfpool.Open(
path,
defaultFileFlags,
@ -277,7 +277,7 @@ func (l *Logger) getFilePointer(path string) *gfpool.File {
)
if err != nil {
// panic(err)
intlog.Error(err)
intlog.Error(ctx, err)
}
return file
}

View File

@ -60,7 +60,7 @@ func (l *Logger) Path(path string) *Logger {
if path != "" {
if err := logger.SetPath(path); err != nil {
// panic(err)
intlog.Error(err)
intlog.Error(l.getCtx(), err)
}
}
return logger
@ -79,7 +79,7 @@ func (l *Logger) Cat(category string) *Logger {
if logger.config.Path != "" {
if err := logger.SetPath(gfile.Join(logger.config.Path, category)); err != nil {
// panic(err)
intlog.Error(err)
intlog.Error(l.getCtx(), err)
}
}
return logger
@ -122,7 +122,7 @@ func (l *Logger) LevelStr(levelStr string) *Logger {
}
if err := logger.SetLevelStr(levelStr); err != nil {
// panic(err)
intlog.Error(err)
intlog.Error(l.getCtx(), err)
}
return logger
}

View File

@ -71,11 +71,11 @@ func (l *Logger) SetConfig(config Config) error {
// Necessary validation.
if config.Path != "" {
if err := l.SetPath(config.Path); err != nil {
intlog.Error(err)
intlog.Error(l.ctx, err)
return err
}
}
intlog.Printf("SetConfig: %+v", l.config)
intlog.Printf(l.ctx, "SetConfig: %+v", l.config)
return nil
}

View File

@ -31,7 +31,7 @@ func (l *Logger) rotateFileBySize(now time.Time) {
}
if err := l.doRotateFile(l.getFilePath(now)); err != nil {
// panic(err)
intlog.Error(err)
intlog.Error(l.ctx, err)
}
}
@ -48,7 +48,11 @@ func (l *Logger) doRotateFile(filePath string) error {
if err := gfile.Remove(filePath); err != nil {
return err
}
intlog.Printf(`%d size exceeds, no backups set, remove original logging file: %s`, l.config.RotateSize, filePath)
intlog.Printf(
l.ctx,
`%d size exceeds, no backups set, remove original logging file: %s`,
l.config.RotateSize, filePath,
)
return nil
}
// Else it creates new backup files.
@ -83,7 +87,7 @@ func (l *Logger) doRotateFile(filePath string) error {
if !gfile.Exists(newFilePath) {
break
} else {
intlog.Printf(`rotation file exists, continue: %s`, newFilePath)
intlog.Printf(l.ctx, `rotation file exists, continue: %s`, newFilePath)
}
}
if err := gfile.Rename(filePath, newFilePath); err != nil {
@ -99,6 +103,7 @@ func (l *Logger) rotateChecksTimely() {
// Checks whether file rotation not enabled.
if l.config.RotateSize <= 0 && l.config.RotateExpire == 0 {
intlog.Printf(
l.ctx,
"logging rotation ignore checks: RotateSize: %d, RotateExpire: %s",
l.config.RotateSize, l.config.RotateExpire.String(),
)
@ -118,9 +123,9 @@ func (l *Logger) rotateChecksTimely() {
files, err = gfile.ScanDirFile(l.config.Path, pattern, true)
)
if err != nil {
intlog.Error(err)
intlog.Error(l.ctx, err)
}
intlog.Printf("logging rotation start checks: %+v", files)
intlog.Printf(l.ctx, "logging rotation start checks: %+v", files)
// =============================================================
// Rotation of expired file checks.
// =============================================================
@ -139,11 +144,12 @@ func (l *Logger) rotateChecksTimely() {
if subDuration > l.config.RotateExpire {
expireRotated = true
intlog.Printf(
l.ctx,
`%v - %v = %v > %v, rotation expire logging file: %s`,
now, mtime, subDuration, l.config.RotateExpire, file,
)
if err := l.doRotateFile(file); err != nil {
intlog.Error(err)
intlog.Error(l.ctx, err)
}
}
}
@ -151,7 +157,7 @@ func (l *Logger) rotateChecksTimely() {
// Update the files array.
files, err = gfile.ScanDirFile(l.config.Path, pattern, true)
if err != nil {
intlog.Error(err)
intlog.Error(l.ctx, err)
}
}
}
@ -176,19 +182,19 @@ func (l *Logger) rotateChecksTimely() {
needCompressFileArray.Iterator(func(_ int, path string) bool {
err := gcompress.GzipFile(path, path+".gz")
if err == nil {
intlog.Printf(`compressed done, remove original logging file: %s`, path)
intlog.Printf(l.ctx, `compressed done, remove original logging file: %s`, path)
if err = gfile.Remove(path); err != nil {
intlog.Print(err)
intlog.Print(l.ctx, err)
}
} else {
intlog.Print(err)
intlog.Print(l.ctx, err)
}
return true
})
// Update the files array.
files, err = gfile.ScanDirFile(l.config.Path, pattern, true)
if err != nil {
intlog.Error(err)
intlog.Error(l.ctx, err)
}
}
}
@ -223,14 +229,14 @@ func (l *Logger) rotateChecksTimely() {
backupFilesMap[originalLoggingFilePath].Add(file)
}
}
intlog.Printf(`calculated backup files map: %+v`, backupFilesMap)
intlog.Printf(l.ctx, `calculated backup files map: %+v`, backupFilesMap)
for _, array := range backupFilesMap {
diff := array.Len() - l.config.RotateBackupLimit
for i := 0; i < diff; i++ {
path, _ := array.PopLeft()
intlog.Printf(`remove exceeded backup limit file: %s`, path)
intlog.Printf(l.ctx, `remove exceeded backup limit file: %s`, path)
if err := gfile.Remove(path.(string)); err != nil {
intlog.Error(err)
intlog.Error(l.ctx, err)
}
}
}
@ -247,11 +253,12 @@ func (l *Logger) rotateChecksTimely() {
subDuration = now.Sub(mtime)
if subDuration > l.config.RotateBackupExpire {
intlog.Printf(
l.ctx,
`%v - %v = %v > %v, remove expired backup file: %s`,
now, mtime, subDuration, l.config.RotateBackupExpire, path,
)
if err := gfile.Remove(path); err != nil {
intlog.Error(err)
intlog.Error(l.ctx, err)
}
return true
} else {

View File

@ -7,6 +7,7 @@
package gproc
import (
"context"
"errors"
"fmt"
"github.com/gogf/gf/internal/intlog"
@ -118,12 +119,11 @@ func (p *Process) Kill() error {
}
if runtime.GOOS != "windows" {
if err = p.Process.Release(); err != nil {
intlog.Error(err)
//return err
intlog.Error(context.TODO(), err)
}
}
_, err = p.Process.Wait()
intlog.Error(err)
intlog.Error(context.TODO(), err)
//return err
return nil
} else {

View File

@ -7,6 +7,7 @@
package gproc
import (
"context"
"github.com/gogf/gf/internal/intlog"
"os"
"os/signal"
@ -67,7 +68,7 @@ func Listen() {
for {
wg := sync.WaitGroup{}
sig = <-sigChan
intlog.Printf(`signal received: %s`, sig.String())
intlog.Printf(context.TODO(), `signal received: %s`, sig.String())
if handlers, ok := signalHandlerMap[sig]; ok {
for _, handler := range handlers {
wg.Add(1)

View File

@ -8,6 +8,7 @@ package gres
import (
"archive/zip"
"context"
"github.com/gogf/gf/internal/fileinfo"
"github.com/gogf/gf/internal/intlog"
"github.com/gogf/gf/os/gfile"
@ -70,7 +71,7 @@ func doZipPathWriter(path string, exclude string, zipWriter *zip.Writer, prefix
headerPrefix = strings.Replace(headerPrefix, "//", "/", -1)
for _, file := range files {
if exclude == file {
intlog.Printf(`exclude file path: %s`, file)
intlog.Printf(context.TODO(), `exclude file path: %s`, file)
continue
}
err = zipFile(file, headerPrefix+gfile.Dir(file[len(path):]), zipWriter)

View File

@ -7,6 +7,7 @@
package gres
import (
"context"
"fmt"
"github.com/gogf/gf/internal/intlog"
"os"
@ -42,7 +43,7 @@ func New() *Resource {
func (r *Resource) Add(content string, prefix ...string) error {
files, err := UnpackContent(content)
if err != nil {
intlog.Printf("Add resource files failed: %v", err)
intlog.Printf(context.TODO(), "Add resource files failed: %v", err)
return err
}
namePrefix := ""
@ -53,7 +54,7 @@ func (r *Resource) Add(content string, prefix ...string) error {
files[i].resource = r
r.tree.Set(namePrefix+files[i].file.Name, files[i])
}
intlog.Printf("Add %d files to resource manager", r.tree.Size())
intlog.Printf(context.TODO(), "Add %d files to resource manager", r.tree.Size())
return nil
}

View File

@ -7,6 +7,7 @@
package gsession
import (
"context"
"github.com/gogf/gf/container/gmap"
"time"
@ -41,13 +42,14 @@ func New(ttl time.Duration, storage ...Storage) *Manager {
// New creates or fetches the session for given session id.
// The parameter <sessionId> is optional, it creates a new one if not it's passed
// depending on Storage.New.
func (m *Manager) New(sessionId ...string) *Session {
func (m *Manager) New(ctx context.Context, sessionId ...string) *Session {
var id string
if len(sessionId) > 0 && sessionId[0] != "" {
id = sessionId[0]
}
return &Session{
id: id,
ctx: ctx,
manager: m,
}
}

View File

@ -7,6 +7,7 @@
package gsession
import (
"context"
"errors"
"github.com/gogf/gf/internal/intlog"
"time"
@ -17,10 +18,12 @@ import (
"github.com/gogf/gf/util/gconv"
)
// Session struct for storing single session data,
// which is bound to a single request.
// Session struct for storing single session data, which is bound to a single request.
// The Session struct is the interface with user, but the Storage is the underlying adapter designed interface
// for functionality implements.
type Session struct {
id string // Session id.
ctx context.Context // Context for current session, note that: one session one context.
data *gmap.StrAnyMap // Session data.
dirty bool // Used to mark session is modified.
start bool // Used to mark session is started.
@ -42,12 +45,12 @@ func (s *Session) init() {
// Retrieve memory session data from manager.
if r, _ := s.manager.sessionData.Get(s.id); r != nil {
s.data = r.(*gmap.StrAnyMap)
intlog.Print("session init data:", s.data)
intlog.Print(s.ctx, "session init data:", s.data)
}
// Retrieve stored session data from storage.
if s.manager.storage != nil {
if s.data, err = s.manager.storage.GetSession(s.id, s.manager.ttl, s.data); err != nil {
intlog.Errorf("session restoring failed for id '%s': %v", s.id, err)
if s.data, err = s.manager.storage.GetSession(s.ctx, s.id, s.manager.ttl, s.data); err != nil {
intlog.Errorf(s.ctx, "session restoring failed for id '%s': %v", s.id, err)
}
}
}
@ -57,7 +60,7 @@ func (s *Session) init() {
}
// Use default session id creating function of storage.
if s.id == "" {
s.id = s.manager.storage.New(s.manager.ttl)
s.id = s.manager.storage.New(s.ctx, s.manager.ttl)
}
// Use default session id creating function.
if s.id == "" {
@ -78,11 +81,11 @@ func (s *Session) Close() {
size := s.data.Size()
if s.manager.storage != nil {
if s.dirty {
if err := s.manager.storage.SetSession(s.id, s.data, s.manager.ttl); err != nil {
if err := s.manager.storage.SetSession(s.ctx, s.id, s.data, s.manager.ttl); err != nil {
panic(err)
}
} else if size > 0 {
if err := s.manager.storage.UpdateTTL(s.id, s.manager.ttl); err != nil {
if err := s.manager.storage.UpdateTTL(s.ctx, s.id, s.manager.ttl); err != nil {
panic(err)
}
}
@ -96,7 +99,7 @@ func (s *Session) Close() {
// Set sets key-value pair to this session.
func (s *Session) Set(key string, value interface{}) error {
s.init()
if err := s.manager.storage.Set(s.id, key, value, s.manager.ttl); err != nil {
if err := s.manager.storage.Set(s.ctx, s.id, key, value, s.manager.ttl); err != nil {
if err == ErrorDisabled {
s.data.Set(key, value)
} else {
@ -116,7 +119,7 @@ func (s *Session) Sets(data map[string]interface{}) error {
// SetMap batch sets the session using map.
func (s *Session) SetMap(data map[string]interface{}) error {
s.init()
if err := s.manager.storage.SetMap(s.id, data, s.manager.ttl); err != nil {
if err := s.manager.storage.SetMap(s.ctx, s.id, data, s.manager.ttl); err != nil {
if err == ErrorDisabled {
s.data.Sets(data)
} else {
@ -134,7 +137,7 @@ func (s *Session) Remove(keys ...string) error {
}
s.init()
for _, key := range keys {
if err := s.manager.storage.Remove(s.id, key); err != nil {
if err := s.manager.storage.Remove(s.ctx, s.id, key); err != nil {
if err == ErrorDisabled {
s.data.Remove(key)
} else {
@ -157,7 +160,7 @@ func (s *Session) RemoveAll() error {
return nil
}
s.init()
if err := s.manager.storage.RemoveAll(s.id); err != nil {
if err := s.manager.storage.RemoveAll(s.ctx, s.id); err != nil {
if err == ErrorDisabled {
s.data.Clear()
} else {
@ -200,7 +203,7 @@ func (s *Session) SetIdFunc(f func(ttl time.Duration) string) error {
func (s *Session) Map() map[string]interface{} {
if s.id != "" {
s.init()
if data := s.manager.storage.GetMap(s.id); data != nil {
if data := s.manager.storage.GetMap(s.ctx, s.id); data != nil {
return data
}
return s.data.Map()
@ -212,7 +215,7 @@ func (s *Session) Map() map[string]interface{} {
func (s *Session) Size() int {
if s.id != "" {
s.init()
if size := s.manager.storage.GetSize(s.id); size >= 0 {
if size := s.manager.storage.GetSize(s.ctx, s.id); size >= 0 {
return size
}
return s.data.Size()
@ -239,7 +242,7 @@ func (s *Session) Get(key string, def ...interface{}) interface{} {
return nil
}
s.init()
if v := s.manager.storage.Get(s.id, key); v != nil {
if v := s.manager.storage.Get(s.ctx, s.id, key); v != nil {
return v
}
if v := s.data.Get(key); v != nil {
@ -363,16 +366,6 @@ func (s *Session) GetStruct(key string, pointer interface{}, mapping ...map[stri
return gconv.Struct(s.Get(key), pointer, mapping...)
}
// Deprecated, use GetStruct instead.
func (s *Session) GetStructDeep(key string, pointer interface{}, mapping ...map[string]string) error {
return gconv.StructDeep(s.Get(key), pointer, mapping...)
}
func (s *Session) GetStructs(key string, pointer interface{}, mapping ...map[string]string) error {
return gconv.Structs(s.Get(key), pointer, mapping...)
}
// Deprecated, use GetStructs instead.
func (s *Session) GetStructsDeep(key string, pointer interface{}, mapping ...map[string]string) error {
return gconv.StructsDeep(s.Get(key), pointer, mapping...)
}

View File

@ -7,6 +7,7 @@
package gsession
import (
"context"
"github.com/gogf/gf/container/gmap"
"time"
)
@ -15,31 +16,31 @@ import (
type Storage interface {
// New creates a custom session id.
// This function can be used for custom session creation.
New(ttl time.Duration) (id string)
New(ctx context.Context, ttl time.Duration) (id string)
// Get retrieves and returns session value with given key.
// It returns nil if the key does not exist in the session.
Get(id string, key string) interface{}
Get(ctx context.Context, id string, key string) interface{}
// GetMap retrieves all key-value pairs as map from storage.
GetMap(id string) map[string]interface{}
GetMap(ctx context.Context, id string) map[string]interface{}
// GetSize retrieves and returns the size of key-value pairs from storage.
GetSize(id string) int
GetSize(ctx context.Context, id string) int
// Set sets one key-value session pair to the storage.
// The parameter <ttl> specifies the TTL for the session id.
Set(id string, key string, value interface{}, ttl time.Duration) error
Set(ctx context.Context, id string, key string, value interface{}, ttl time.Duration) error
// SetMap batch sets key-value session pairs as map to the storage.
// The parameter <ttl> specifies the TTL for the session id.
SetMap(id string, data map[string]interface{}, ttl time.Duration) error
SetMap(ctx context.Context, id string, data map[string]interface{}, ttl time.Duration) error
// Remove deletes key with its value from storage.
Remove(id string, key string) error
Remove(ctx context.Context, id string, key string) error
// RemoveAll deletes all key-value pairs from storage.
RemoveAll(id string) error
RemoveAll(ctx context.Context, id string) error
// GetSession returns the session data as *gmap.StrAnyMap for given session id from storage.
//
@ -48,14 +49,14 @@ type Storage interface {
// and for some storage it might be nil if memory storage is disabled.
//
// This function is called ever when session starts. It returns nil if the TTL is exceeded.
GetSession(id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error)
GetSession(ctx context.Context, id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error)
// SetSession updates the data for specified session id.
// This function is called ever after session, which is changed dirty, is closed.
// This copy all session data map from memory to storage.
SetSession(id string, data *gmap.StrAnyMap, ttl time.Duration) error
SetSession(ctx context.Context, id string, data *gmap.StrAnyMap, ttl time.Duration) error
// UpdateTTL updates the TTL for specified session id.
// This function is called ever after session, which is not dirty, is closed.
UpdateTTL(id string, ttl time.Duration) error
UpdateTTL(ctx context.Context, id string, ttl time.Duration) error
}

View File

@ -7,6 +7,7 @@
package gsession
import (
"context"
"github.com/gogf/gf/container/gmap"
"github.com/gogf/gf/errors/gerror"
"github.com/gogf/gf/internal/intlog"
@ -80,8 +81,8 @@ func (s *StorageFile) updateSessionTimely() {
if id = s.updatingIdSet.Pop(); id == "" {
break
}
if err = s.updateSessionTTl(id); err != nil {
intlog.Error(err)
if err = s.updateSessionTTl(context.TODO(), id); err != nil {
intlog.Error(context.TODO(), err)
}
}
}
@ -104,45 +105,45 @@ func (s *StorageFile) sessionFilePath(id string) string {
// New creates a session id.
// This function can be used for custom session creation.
func (s *StorageFile) New(ttl time.Duration) (id string) {
func (s *StorageFile) New(ctx context.Context, ttl time.Duration) (id string) {
return ""
}
// Get retrieves session value with given key.
// It returns nil if the key does not exist in the session.
func (s *StorageFile) Get(id string, key string) interface{} {
func (s *StorageFile) Get(ctx context.Context, id string, key string) interface{} {
return nil
}
// GetMap retrieves all key-value pairs as map from storage.
func (s *StorageFile) GetMap(id string) map[string]interface{} {
func (s *StorageFile) GetMap(ctx context.Context, id string) map[string]interface{} {
return nil
}
// GetSize retrieves the size of key-value pairs from storage.
func (s *StorageFile) GetSize(id string) int {
func (s *StorageFile) GetSize(ctx context.Context, id string) int {
return -1
}
// Set sets key-value session pair to the storage.
// The parameter <ttl> specifies the TTL for the session id (not for the key-value pair).
func (s *StorageFile) Set(id string, key string, value interface{}, ttl time.Duration) error {
func (s *StorageFile) Set(ctx context.Context, id string, key string, value interface{}, ttl time.Duration) error {
return ErrorDisabled
}
// SetMap batch sets key-value session pairs with map to the storage.
// The parameter <ttl> specifies the TTL for the session id(not for the key-value pair).
func (s *StorageFile) SetMap(id string, data map[string]interface{}, ttl time.Duration) error {
func (s *StorageFile) SetMap(ctx context.Context, id string, data map[string]interface{}, ttl time.Duration) error {
return ErrorDisabled
}
// Remove deletes key with its value from storage.
func (s *StorageFile) Remove(id string, key string) error {
func (s *StorageFile) Remove(ctx context.Context, id string, key string) error {
return ErrorDisabled
}
// RemoveAll deletes all key-value pairs from storage.
func (s *StorageFile) RemoveAll(id string) error {
func (s *StorageFile) RemoveAll(ctx context.Context, id string) error {
return ErrorDisabled
}
@ -153,11 +154,10 @@ func (s *StorageFile) RemoveAll(id string) error {
// and for some storage it might be nil if memory storage is disabled.
//
// This function is called ever when session starts.
func (s *StorageFile) GetSession(id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error) {
func (s *StorageFile) GetSession(ctx context.Context, id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error) {
if data != nil {
return data, nil
}
//intlog.Printf("StorageFile.GetSession: %s, %v", id, ttl)
path := s.sessionFilePath(id)
content := gfile.GetBytes(path)
if len(content) > 8 {
@ -189,8 +189,8 @@ func (s *StorageFile) GetSession(id string, ttl time.Duration, data *gmap.StrAny
// SetSession updates the data map for specified session id.
// This function is called ever after session, which is changed dirty, is closed.
// This copy all session data map from memory to storage.
func (s *StorageFile) SetSession(id string, data *gmap.StrAnyMap, ttl time.Duration) error {
intlog.Printf("StorageFile.SetSession: %s, %v, %v", id, data, ttl)
func (s *StorageFile) SetSession(ctx context.Context, id string, data *gmap.StrAnyMap, ttl time.Duration) error {
intlog.Printf(ctx, "StorageFile.SetSession: %s, %v, %v", id, data, ttl)
path := s.sessionFilePath(id)
content, err := json.Marshal(data)
if err != nil {
@ -222,8 +222,8 @@ func (s *StorageFile) SetSession(id string, data *gmap.StrAnyMap, ttl time.Durat
// UpdateTTL updates the TTL for specified session id.
// This function is called ever after session, which is not dirty, is closed.
// It just adds the session id to the async handling queue.
func (s *StorageFile) UpdateTTL(id string, ttl time.Duration) error {
intlog.Printf("StorageFile.UpdateTTL: %s, %v", id, ttl)
func (s *StorageFile) UpdateTTL(ctx context.Context, id string, ttl time.Duration) error {
intlog.Printf(ctx, "StorageFile.UpdateTTL: %s, %v", id, ttl)
if ttl >= DefaultStorageFileLoopInterval {
s.updatingIdSet.Add(id)
}
@ -231,8 +231,8 @@ func (s *StorageFile) UpdateTTL(id string, ttl time.Duration) error {
}
// updateSessionTTL updates the TTL for specified session id.
func (s *StorageFile) updateSessionTTl(id string) error {
intlog.Printf("StorageFile.updateSession: %s", id)
func (s *StorageFile) updateSessionTTl(ctx context.Context, id string) error {
intlog.Printf(ctx, "StorageFile.updateSession: %s", id)
path := s.sessionFilePath(id)
file, err := gfile.OpenWithFlag(path, os.O_WRONLY)
if err != nil {

View File

@ -7,6 +7,7 @@
package gsession
import (
"context"
"github.com/gogf/gf/container/gmap"
"time"
)
@ -21,45 +22,45 @@ func NewStorageMemory() *StorageMemory {
// New creates a session id.
// This function can be used for custom session creation.
func (s *StorageMemory) New(ttl time.Duration) (id string) {
func (s *StorageMemory) New(ctx context.Context, ttl time.Duration) (id string) {
return ""
}
// Get retrieves session value with given key.
// It returns nil if the key does not exist in the session.
func (s *StorageMemory) Get(id string, key string) interface{} {
func (s *StorageMemory) Get(ctx context.Context, id string, key string) interface{} {
return nil
}
// GetMap retrieves all key-value pairs as map from storage.
func (s *StorageMemory) GetMap(id string) map[string]interface{} {
func (s *StorageMemory) GetMap(ctx context.Context, id string) map[string]interface{} {
return nil
}
// GetSize retrieves the size of key-value pairs from storage.
func (s *StorageMemory) GetSize(id string) int {
func (s *StorageMemory) GetSize(ctx context.Context, id string) int {
return -1
}
// Set sets key-value session pair to the storage.
// The parameter <ttl> specifies the TTL for the session id (not for the key-value pair).
func (s *StorageMemory) Set(id string, key string, value interface{}, ttl time.Duration) error {
func (s *StorageMemory) Set(ctx context.Context, id string, key string, value interface{}, ttl time.Duration) error {
return ErrorDisabled
}
// SetMap batch sets key-value session pairs with map to the storage.
// The parameter <ttl> specifies the TTL for the session id(not for the key-value pair).
func (s *StorageMemory) SetMap(id string, data map[string]interface{}, ttl time.Duration) error {
func (s *StorageMemory) SetMap(ctx context.Context, id string, data map[string]interface{}, ttl time.Duration) error {
return ErrorDisabled
}
// Remove deletes key with its value from storage.
func (s *StorageMemory) Remove(id string, key string) error {
func (s *StorageMemory) Remove(ctx context.Context, id string, key string) error {
return ErrorDisabled
}
// RemoveAll deletes all key-value pairs from storage.
func (s *StorageMemory) RemoveAll(id string) error {
func (s *StorageMemory) RemoveAll(ctx context.Context, id string) error {
return ErrorDisabled
}
@ -70,25 +71,20 @@ func (s *StorageMemory) RemoveAll(id string) error {
// and for some storage it might be nil if memory storage is disabled.
//
// This function is called ever when session starts.
func (s *StorageMemory) GetSession(id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error) {
func (s *StorageMemory) GetSession(ctx context.Context, id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error) {
return data, nil
}
// SetSession updates the data map for specified session id.
// This function is called ever after session, which is changed dirty, is closed.
// This copy all session data map from memory to storage.
func (s *StorageMemory) SetSession(id string, data *gmap.StrAnyMap, ttl time.Duration) error {
func (s *StorageMemory) SetSession(ctx context.Context, id string, data *gmap.StrAnyMap, ttl time.Duration) error {
return nil
}
// UpdateTTL updates the TTL for specified session id.
// This function is called ever after session, which is not dirty, is closed.
// It just adds the session id to the async handling queue.
func (s *StorageMemory) UpdateTTL(id string, ttl time.Duration) error {
return nil
}
// doUpdateTTL updates the TTL for session id.
func (s *StorageMemory) doUpdateTTL(id string) error {
func (s *StorageMemory) UpdateTTL(ctx context.Context, id string, ttl time.Duration) error {
return nil
}

View File

@ -7,6 +7,7 @@
package gsession
import (
"context"
"github.com/gogf/gf/container/gmap"
"github.com/gogf/gf/database/gredis"
"github.com/gogf/gf/internal/intlog"
@ -44,7 +45,7 @@ func NewStorageRedis(redis *gredis.Redis, prefix ...string) *StorageRedis {
}
// Batch updates the TTL for session ids timely.
gtimer.AddSingleton(DefaultStorageRedisLoopInterval, func() {
intlog.Print("StorageRedis.timer start")
intlog.Print(context.TODO(), "StorageRedis.timer start")
var (
id string
err error
@ -54,57 +55,57 @@ func NewStorageRedis(redis *gredis.Redis, prefix ...string) *StorageRedis {
if id, ttlSeconds = s.updatingIdMap.Pop(); id == "" {
break
} else {
if err = s.doUpdateTTL(id, ttlSeconds); err != nil {
intlog.Error(err)
if err = s.doUpdateTTL(context.TODO(), id, ttlSeconds); err != nil {
intlog.Error(context.TODO(), err)
}
}
}
intlog.Print("StorageRedis.timer end")
intlog.Print(context.TODO(), "StorageRedis.timer end")
})
return s
}
// New creates a session id.
// This function can be used for custom session creation.
func (s *StorageRedis) New(ttl time.Duration) (id string) {
func (s *StorageRedis) New(ctx context.Context, ttl time.Duration) (id string) {
return ""
}
// Get retrieves session value with given key.
// It returns nil if the key does not exist in the session.
func (s *StorageRedis) Get(id string, key string) interface{} {
func (s *StorageRedis) Get(ctx context.Context, id string, key string) interface{} {
return nil
}
// GetMap retrieves all key-value pairs as map from storage.
func (s *StorageRedis) GetMap(id string) map[string]interface{} {
func (s *StorageRedis) GetMap(ctx context.Context, id string) map[string]interface{} {
return nil
}
// GetSize retrieves the size of key-value pairs from storage.
func (s *StorageRedis) GetSize(id string) int {
func (s *StorageRedis) GetSize(ctx context.Context, id string) int {
return -1
}
// Set sets key-value session pair to the storage.
// The parameter <ttl> specifies the TTL for the session id (not for the key-value pair).
func (s *StorageRedis) Set(id string, key string, value interface{}, ttl time.Duration) error {
func (s *StorageRedis) Set(ctx context.Context, id string, key string, value interface{}, ttl time.Duration) error {
return ErrorDisabled
}
// SetMap batch sets key-value session pairs with map to the storage.
// The parameter <ttl> specifies the TTL for the session id(not for the key-value pair).
func (s *StorageRedis) SetMap(id string, data map[string]interface{}, ttl time.Duration) error {
func (s *StorageRedis) SetMap(ctx context.Context, id string, data map[string]interface{}, ttl time.Duration) error {
return ErrorDisabled
}
// Remove deletes key with its value from storage.
func (s *StorageRedis) Remove(id string, key string) error {
func (s *StorageRedis) Remove(ctx context.Context, id string, key string) error {
return ErrorDisabled
}
// RemoveAll deletes all key-value pairs from storage.
func (s *StorageRedis) RemoveAll(id string) error {
func (s *StorageRedis) RemoveAll(ctx context.Context, id string) error {
return ErrorDisabled
}
@ -115,9 +116,9 @@ func (s *StorageRedis) RemoveAll(id string) error {
// and for some storage it might be nil if memory storage is disabled.
//
// This function is called ever when session starts.
func (s *StorageRedis) GetSession(id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error) {
intlog.Printf("StorageRedis.GetSession: %s, %v", id, ttl)
r, err := s.redis.DoVar("GET", s.key(id))
func (s *StorageRedis) GetSession(ctx context.Context, id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error) {
intlog.Printf(ctx, "StorageRedis.GetSession: %s, %v", id, ttl)
r, err := s.redis.Ctx(ctx).DoVar("GET", s.key(id))
if err != nil {
return nil, err
}
@ -143,21 +144,21 @@ func (s *StorageRedis) GetSession(id string, ttl time.Duration, data *gmap.StrAn
// SetSession updates the data map for specified session id.
// This function is called ever after session, which is changed dirty, is closed.
// This copy all session data map from memory to storage.
func (s *StorageRedis) SetSession(id string, data *gmap.StrAnyMap, ttl time.Duration) error {
intlog.Printf("StorageRedis.SetSession: %s, %v, %v", id, data, ttl)
func (s *StorageRedis) SetSession(ctx context.Context, id string, data *gmap.StrAnyMap, ttl time.Duration) error {
intlog.Printf(ctx, "StorageRedis.SetSession: %s, %v, %v", id, data, ttl)
content, err := json.Marshal(data)
if err != nil {
return err
}
_, err = s.redis.DoVar("SETEX", s.key(id), int64(ttl.Seconds()), content)
_, err = s.redis.Ctx(ctx).DoVar("SETEX", s.key(id), int64(ttl.Seconds()), content)
return err
}
// UpdateTTL updates the TTL for specified session id.
// This function is called ever after session, which is not dirty, is closed.
// It just adds the session id to the async handling queue.
func (s *StorageRedis) UpdateTTL(id string, ttl time.Duration) error {
intlog.Printf("StorageRedis.UpdateTTL: %s, %v", id, ttl)
func (s *StorageRedis) UpdateTTL(ctx context.Context, id string, ttl time.Duration) error {
intlog.Printf(ctx, "StorageRedis.UpdateTTL: %s, %v", id, ttl)
if ttl >= DefaultStorageRedisLoopInterval {
s.updatingIdMap.Set(id, int(ttl.Seconds()))
}
@ -165,9 +166,9 @@ func (s *StorageRedis) UpdateTTL(id string, ttl time.Duration) error {
}
// doUpdateTTL updates the TTL for session id.
func (s *StorageRedis) doUpdateTTL(id string, ttlSeconds int) error {
intlog.Printf("StorageRedis.doUpdateTTL: %s, %d", id, ttlSeconds)
_, err := s.redis.DoVar("EXPIRE", s.key(id), ttlSeconds)
func (s *StorageRedis) doUpdateTTL(ctx context.Context, id string, ttlSeconds int) error {
intlog.Printf(ctx, "StorageRedis.doUpdateTTL: %s, %d", id, ttlSeconds)
_, err := s.redis.Ctx(ctx).DoVar("EXPIRE", s.key(id), ttlSeconds)
return err
}

View File

@ -7,6 +7,7 @@
package gsession
import (
"context"
"time"
"github.com/gogf/gf/container/gmap"
@ -38,14 +39,14 @@ func NewStorageRedisHashTable(redis *gredis.Redis, prefix ...string) *StorageRed
// New creates a session id.
// This function can be used for custom session creation.
func (s *StorageRedisHashTable) New(ttl time.Duration) (id string) {
func (s *StorageRedisHashTable) New(ctx context.Context, ttl time.Duration) (id string) {
return ""
}
// Get retrieves session value with given key.
// It returns nil if the key does not exist in the session.
func (s *StorageRedisHashTable) Get(id string, key string) interface{} {
r, _ := s.redis.Do("HGET", s.key(id), key)
func (s *StorageRedisHashTable) Get(ctx context.Context, id string, key string) interface{} {
r, _ := s.redis.Ctx(ctx).Do("HGET", s.key(id), key)
if r != nil {
return gconv.String(r)
}
@ -53,8 +54,8 @@ func (s *StorageRedisHashTable) Get(id string, key string) interface{} {
}
// GetMap retrieves all key-value pairs as map from storage.
func (s *StorageRedisHashTable) GetMap(id string) map[string]interface{} {
r, err := s.redis.DoVar("HGETALL", s.key(id))
func (s *StorageRedisHashTable) GetMap(ctx context.Context, id string) map[string]interface{} {
r, err := s.redis.Ctx(ctx).DoVar("HGETALL", s.key(id))
if err != nil {
return nil
}
@ -71,21 +72,21 @@ func (s *StorageRedisHashTable) GetMap(id string) map[string]interface{} {
}
// GetSize retrieves the size of key-value pairs from storage.
func (s *StorageRedisHashTable) GetSize(id string) int {
r, _ := s.redis.DoVar("HLEN", s.key(id))
func (s *StorageRedisHashTable) GetSize(ctx context.Context, id string) int {
r, _ := s.redis.Ctx(ctx).DoVar("HLEN", s.key(id))
return r.Int()
}
// Set sets key-value session pair to the storage.
// The parameter <ttl> specifies the TTL for the session id (not for the key-value pair).
func (s *StorageRedisHashTable) Set(id string, key string, value interface{}, ttl time.Duration) error {
_, err := s.redis.Do("HSET", s.key(id), key, value)
func (s *StorageRedisHashTable) Set(ctx context.Context, id string, key string, value interface{}, ttl time.Duration) error {
_, err := s.redis.Ctx(ctx).Do("HSET", s.key(id), key, value)
return err
}
// SetMap batch sets key-value session pairs with map to the storage.
// The parameter <ttl> specifies the TTL for the session id(not for the key-value pair).
func (s *StorageRedisHashTable) SetMap(id string, data map[string]interface{}, ttl time.Duration) error {
func (s *StorageRedisHashTable) SetMap(ctx context.Context, id string, data map[string]interface{}, ttl time.Duration) error {
array := make([]interface{}, len(data)*2+1)
array[0] = s.key(id)
@ -95,19 +96,19 @@ func (s *StorageRedisHashTable) SetMap(id string, data map[string]interface{}, t
array[index+1] = v
index += 2
}
_, err := s.redis.Do("HMSET", array...)
_, err := s.redis.Ctx(ctx).Do("HMSET", array...)
return err
}
// Remove deletes key with its value from storage.
func (s *StorageRedisHashTable) Remove(id string, key string) error {
_, err := s.redis.Do("HDEL", s.key(id), key)
func (s *StorageRedisHashTable) Remove(ctx context.Context, id string, key string) error {
_, err := s.redis.Ctx(ctx).Do("HDEL", s.key(id), key)
return err
}
// RemoveAll deletes all key-value pairs from storage.
func (s *StorageRedisHashTable) RemoveAll(id string) error {
_, err := s.redis.Do("DEL", s.key(id))
func (s *StorageRedisHashTable) RemoveAll(ctx context.Context, id string) error {
_, err := s.redis.Ctx(ctx).Do("DEL", s.key(id))
return err
}
@ -118,9 +119,9 @@ func (s *StorageRedisHashTable) RemoveAll(id string) error {
// and for some storage it might be nil if memory storage is disabled.
//
// This function is called ever when session starts.
func (s *StorageRedisHashTable) GetSession(id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error) {
intlog.Printf("StorageRedisHashTable.GetSession: %s, %v", id, ttl)
r, err := s.redis.DoVar("EXISTS", s.key(id))
func (s *StorageRedisHashTable) GetSession(ctx context.Context, id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error) {
intlog.Printf(ctx, "StorageRedisHashTable.GetSession: %s, %v", id, ttl)
r, err := s.redis.Ctx(ctx).DoVar("EXISTS", s.key(id))
if err != nil {
return nil, err
}
@ -133,17 +134,17 @@ func (s *StorageRedisHashTable) GetSession(id string, ttl time.Duration, data *g
// SetSession updates the data map for specified session id.
// This function is called ever after session, which is changed dirty, is closed.
// This copy all session data map from memory to storage.
func (s *StorageRedisHashTable) SetSession(id string, data *gmap.StrAnyMap, ttl time.Duration) error {
intlog.Printf("StorageRedisHashTable.SetSession: %s, %v", id, ttl)
_, err := s.redis.Do("EXPIRE", s.key(id), int64(ttl.Seconds()))
func (s *StorageRedisHashTable) SetSession(ctx context.Context, id string, data *gmap.StrAnyMap, ttl time.Duration) error {
intlog.Printf(ctx, "StorageRedisHashTable.SetSession: %s, %v", id, ttl)
_, err := s.redis.Ctx(ctx).Do("EXPIRE", s.key(id), int64(ttl.Seconds()))
return err
}
// UpdateTTL updates the TTL for specified session id.
// This function is called ever after session, which is not dirty, is closed.
// It just adds the session id to the async handling queue.
func (s *StorageRedisHashTable) UpdateTTL(id string, ttl time.Duration) error {
intlog.Printf("StorageRedisHashTable.UpdateTTL: %s, %v", id, ttl)
func (s *StorageRedisHashTable) UpdateTTL(ctx context.Context, id string, ttl time.Duration) error {
intlog.Printf(ctx, "StorageRedisHashTable.UpdateTTL: %s, %v", id, ttl)
_, err := s.redis.Do("EXPIRE", s.key(id), int64(ttl.Seconds()))
return err
}

View File

@ -7,6 +7,7 @@
package gsession_test
import (
"context"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gsession"
"testing"
@ -20,7 +21,7 @@ func Test_StorageFile(t *testing.T) {
manager := gsession.New(time.Second, storage)
sessionId := ""
gtest.C(t, func(t *gtest.T) {
s := manager.New()
s := manager.New(context.TODO())
defer s.Close()
s.Set("k1", "v1")
s.Set("k2", "v2")
@ -34,7 +35,7 @@ func Test_StorageFile(t *testing.T) {
time.Sleep(500 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Get("k1"), "v1")
t.Assert(s.Get("k2"), "v2")
t.Assert(s.Get("k3"), "v3")
@ -66,7 +67,7 @@ func Test_StorageFile(t *testing.T) {
time.Sleep(1000 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Size(), 0)
t.Assert(s.Get("k5"), nil)
t.Assert(s.Get("k6"), nil)

View File

@ -7,6 +7,7 @@
package gsession_test
import (
"context"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gsession"
"testing"
@ -20,7 +21,7 @@ func Test_StorageMemory(t *testing.T) {
manager := gsession.New(time.Second, storage)
sessionId := ""
gtest.C(t, func(t *gtest.T) {
s := manager.New()
s := manager.New(context.TODO())
defer s.Close()
s.Set("k1", "v1")
s.Set("k2", "v2")
@ -34,7 +35,7 @@ func Test_StorageMemory(t *testing.T) {
time.Sleep(500 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Get("k1"), "v1")
t.Assert(s.Get("k2"), "v2")
t.Assert(s.Get("k3"), "v3")
@ -66,7 +67,7 @@ func Test_StorageMemory(t *testing.T) {
time.Sleep(1000 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Size(), 0)
t.Assert(s.Get("k5"), nil)
t.Assert(s.Get("k6"), nil)

View File

@ -7,6 +7,7 @@
package gsession_test
import (
"context"
"github.com/gogf/gf/database/gredis"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gsession"
@ -26,7 +27,7 @@ func Test_StorageRedisHashTable(t *testing.T) {
manager := gsession.New(time.Second, storage)
sessionId := ""
gtest.C(t, func(t *gtest.T) {
s := manager.New()
s := manager.New(context.TODO())
defer s.Close()
s.Set("k1", "v1")
s.Set("k2", "v2")
@ -38,7 +39,7 @@ func Test_StorageRedisHashTable(t *testing.T) {
sessionId = s.Id()
})
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Get("k1"), "v1")
t.Assert(s.Get("k2"), "v2")
t.Assert(s.Get("k3"), "v3")
@ -71,7 +72,7 @@ func Test_StorageRedisHashTable(t *testing.T) {
time.Sleep(1500 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Size(), 0)
t.Assert(s.Get("k5"), nil)
t.Assert(s.Get("k6"), nil)
@ -89,7 +90,7 @@ func Test_StorageRedisHashTablePrefix(t *testing.T) {
manager := gsession.New(time.Second, storage)
sessionId := ""
gtest.C(t, func(t *gtest.T) {
s := manager.New()
s := manager.New(context.TODO())
defer s.Close()
s.Set("k1", "v1")
s.Set("k2", "v2")
@ -101,7 +102,7 @@ func Test_StorageRedisHashTablePrefix(t *testing.T) {
sessionId = s.Id()
})
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Get("k1"), "v1")
t.Assert(s.Get("k2"), "v2")
t.Assert(s.Get("k3"), "v3")
@ -134,7 +135,7 @@ func Test_StorageRedisHashTablePrefix(t *testing.T) {
time.Sleep(1500 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Size(), 0)
t.Assert(s.Get("k5"), nil)
t.Assert(s.Get("k6"), nil)

View File

@ -7,6 +7,7 @@
package gsession_test
import (
"context"
"github.com/gogf/gf/database/gredis"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gsession"
@ -24,7 +25,7 @@ func Test_StorageRedis(t *testing.T) {
manager := gsession.New(time.Second, storage)
sessionId := ""
gtest.C(t, func(t *gtest.T) {
s := manager.New()
s := manager.New(context.TODO())
defer s.Close()
s.Set("k1", "v1")
s.Set("k2", "v2")
@ -38,7 +39,7 @@ func Test_StorageRedis(t *testing.T) {
time.Sleep(500 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Get("k1"), "v1")
t.Assert(s.Get("k2"), "v2")
t.Assert(s.Get("k3"), "v3")
@ -70,7 +71,7 @@ func Test_StorageRedis(t *testing.T) {
time.Sleep(1000 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Size(), 0)
t.Assert(s.Get("k5"), nil)
t.Assert(s.Get("k6"), nil)
@ -86,7 +87,7 @@ func Test_StorageRedisPrefix(t *testing.T) {
manager := gsession.New(time.Second, storage)
sessionId := ""
gtest.C(t, func(t *gtest.T) {
s := manager.New()
s := manager.New(context.TODO())
defer s.Close()
s.Set("k1", "v1")
s.Set("k2", "v2")
@ -100,7 +101,7 @@ func Test_StorageRedisPrefix(t *testing.T) {
time.Sleep(500 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Get("k1"), "v1")
t.Assert(s.Get("k2"), "v2")
t.Assert(s.Get("k3"), "v3")
@ -132,7 +133,7 @@ func Test_StorageRedisPrefix(t *testing.T) {
time.Sleep(1000 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
s := manager.New(sessionId)
s := manager.New(context.TODO(), sessionId)
t.Assert(s.Size(), 0)
t.Assert(s.Get("k5"), nil)
t.Assert(s.Get("k6"), nil)

View File

@ -12,6 +12,7 @@
package gspath
import (
"context"
"errors"
"fmt"
"github.com/gogf/gf/internal/intlog"
@ -113,7 +114,7 @@ func (sp *SPath) Set(path string) (realPath string, err error) {
sp.removeMonitorByPath(v)
}
}
intlog.Print("paths clear:", sp.paths)
intlog.Print(context.TODO(), "paths clear:", sp.paths)
sp.paths.Clear()
if sp.cache != nil {
sp.cache.Clear()

View File

@ -72,14 +72,14 @@ func New(path ...string) *View {
}
if len(path) > 0 && len(path[0]) > 0 {
if err := view.SetPath(path[0]); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
} else {
// Customized dir path from env/cmd.
if envPath := gcmd.GetOptWithEnv(commandEnvKeyForPath).String(); envPath != "" {
if gfile.Exists(envPath) {
if err := view.SetPath(envPath); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
} else {
if errorPrint() {
@ -89,18 +89,18 @@ func New(path ...string) *View {
} else {
// Dir path of working dir.
if err := view.SetPath(gfile.Pwd()); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
// Dir path of binary.
if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) {
if err := view.AddPath(selfPath); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
}
// Dir path of main package.
if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) {
if err := view.AddPath(mainPath); err != nil {
intlog.Error(err)
intlog.Error(context.TODO(), err)
}
}
}

View File

@ -7,6 +7,7 @@
package gview
import (
"context"
"errors"
"fmt"
"github.com/gogf/gf/i18n/gi18n"
@ -67,7 +68,7 @@ func (view *View) SetConfig(config Config) error {
// It's just cache, do not hesitate clearing it.
templates.Clear()
intlog.Printf("SetConfig: %+v", view.config)
intlog.Printf(context.TODO(), "SetConfig: %+v", view.config)
return nil
}

View File

@ -83,7 +83,7 @@ func (view *View) Parse(ctx context.Context, file string, params ...Params) (res
templates.Clear()
gfsnotify.Exit()
}); err != nil {
intlog.Error(err)
intlog.Error(ctx, err)
}
}
return &fileCacheItem{

View File

@ -46,238 +46,254 @@ var (
StructTagPriority = []string{"gconv", "param", "params", "c", "p", "json"}
)
// Convert converts the variable `any` to the type `t`, the type `t` is specified by string.
// The optional parameter `params` is used for additional necessary parameter for this conversion.
// It supports common types conversion as its conversion based on type name string.
func Convert(any interface{}, t string, params ...interface{}) interface{} {
switch t {
type doConvertInput struct {
FromValue interface{} // Value that is converted from.
ToTypeName string // Target value type name in string.
ReferValue interface{} // Referred value, a value in type `ToTypeName`.
Extra []interface{} // Extra values for implementing the converting.
}
func doConvert(input doConvertInput) interface{} {
switch input.ToTypeName {
case "int":
return Int(any)
return Int(input.FromValue)
case "*int":
if _, ok := any.(*int); ok {
return any
if _, ok := input.FromValue.(*int); ok {
return input.FromValue
}
v := Int(any)
v := Int(input.FromValue)
return &v
case "int8":
return Int8(any)
return Int8(input.FromValue)
case "*int8":
if _, ok := any.(*int8); ok {
return any
if _, ok := input.FromValue.(*int8); ok {
return input.FromValue
}
v := Int8(any)
v := Int8(input.FromValue)
return &v
case "int16":
return Int16(any)
return Int16(input.FromValue)
case "*int16":
if _, ok := any.(*int16); ok {
return any
if _, ok := input.FromValue.(*int16); ok {
return input.FromValue
}
v := Int16(any)
v := Int16(input.FromValue)
return &v
case "int32":
return Int32(any)
return Int32(input.FromValue)
case "*int32":
if _, ok := any.(*int32); ok {
return any
if _, ok := input.FromValue.(*int32); ok {
return input.FromValue
}
v := Int32(any)
v := Int32(input.FromValue)
return &v
case "int64":
return Int64(any)
return Int64(input.FromValue)
case "*int64":
if _, ok := any.(*int64); ok {
return any
if _, ok := input.FromValue.(*int64); ok {
return input.FromValue
}
v := Int64(any)
v := Int64(input.FromValue)
return &v
case "uint":
return Uint(any)
return Uint(input.FromValue)
case "*uint":
if _, ok := any.(*uint); ok {
return any
if _, ok := input.FromValue.(*uint); ok {
return input.FromValue
}
v := Uint(any)
v := Uint(input.FromValue)
return &v
case "uint8":
return Uint8(any)
return Uint8(input.FromValue)
case "*uint8":
if _, ok := any.(*uint8); ok {
return any
if _, ok := input.FromValue.(*uint8); ok {
return input.FromValue
}
v := Uint8(any)
v := Uint8(input.FromValue)
return &v
case "uint16":
return Uint16(any)
return Uint16(input.FromValue)
case "*uint16":
if _, ok := any.(*uint16); ok {
return any
if _, ok := input.FromValue.(*uint16); ok {
return input.FromValue
}
v := Uint16(any)
v := Uint16(input.FromValue)
return &v
case "uint32":
return Uint32(any)
return Uint32(input.FromValue)
case "*uint32":
if _, ok := any.(*uint32); ok {
return any
if _, ok := input.FromValue.(*uint32); ok {
return input.FromValue
}
v := Uint32(any)
v := Uint32(input.FromValue)
return &v
case "uint64":
return Uint64(any)
return Uint64(input.FromValue)
case "*uint64":
if _, ok := any.(*uint64); ok {
return any
if _, ok := input.FromValue.(*uint64); ok {
return input.FromValue
}
v := Uint64(any)
v := Uint64(input.FromValue)
return &v
case "float32":
return Float32(any)
return Float32(input.FromValue)
case "*float32":
if _, ok := any.(*float32); ok {
return any
if _, ok := input.FromValue.(*float32); ok {
return input.FromValue
}
v := Float32(any)
v := Float32(input.FromValue)
return &v
case "float64":
return Float64(any)
return Float64(input.FromValue)
case "*float64":
if _, ok := any.(*float64); ok {
return any
if _, ok := input.FromValue.(*float64); ok {
return input.FromValue
}
v := Float64(any)
v := Float64(input.FromValue)
return &v
case "bool":
return Bool(any)
return Bool(input.FromValue)
case "*bool":
if _, ok := any.(*bool); ok {
return any
if _, ok := input.FromValue.(*bool); ok {
return input.FromValue
}
v := Bool(any)
v := Bool(input.FromValue)
return &v
case "string":
return String(any)
return String(input.FromValue)
case "*string":
if _, ok := any.(*string); ok {
return any
if _, ok := input.FromValue.(*string); ok {
return input.FromValue
}
v := String(any)
v := String(input.FromValue)
return &v
case "[]byte":
return Bytes(any)
return Bytes(input.FromValue)
case "[]int":
return Ints(any)
return Ints(input.FromValue)
case "[]int32":
return Int32s(any)
return Int32s(input.FromValue)
case "[]int64":
return Int64s(any)
return Int64s(input.FromValue)
case "[]uint":
return Uints(any)
return Uints(input.FromValue)
case "[]uint32":
return Uint32s(any)
return Uint32s(input.FromValue)
case "[]uint64":
return Uint64s(any)
return Uint64s(input.FromValue)
case "[]float32":
return Float32s(any)
return Float32s(input.FromValue)
case "[]float64":
return Float64s(any)
return Float64s(input.FromValue)
case "[]string":
return Strings(any)
return Strings(input.FromValue)
case "Time", "time.Time":
if len(params) > 0 {
return Time(any, String(params[0]))
if len(input.Extra) > 0 {
return Time(input.FromValue, String(input.Extra[0]))
}
return Time(any)
return Time(input.FromValue)
case "*time.Time":
var v interface{}
if len(params) > 0 {
v = Time(any, String(params[0]))
if len(input.Extra) > 0 {
v = Time(input.FromValue, String(input.Extra[0]))
} else {
if _, ok := any.(*time.Time); ok {
return any
if _, ok := input.FromValue.(*time.Time); ok {
return input.FromValue
}
v = Time(any)
v = Time(input.FromValue)
}
return &v
case "GTime", "gtime.Time":
if len(params) > 0 {
if v := GTime(any, String(params[0])); v != nil {
if len(input.Extra) > 0 {
if v := GTime(input.FromValue, String(input.Extra[0])); v != nil {
return *v
} else {
return *gtime.New()
}
}
if v := GTime(any); v != nil {
if v := GTime(input.FromValue); v != nil {
return *v
} else {
return *gtime.New()
}
case "*gtime.Time":
if len(params) > 0 {
if v := GTime(any, String(params[0])); v != nil {
if len(input.Extra) > 0 {
if v := GTime(input.FromValue, String(input.Extra[0])); v != nil {
return v
} else {
return gtime.New()
}
}
if v := GTime(any); v != nil {
if v := GTime(input.FromValue); v != nil {
return v
} else {
return gtime.New()
}
case "Duration", "time.Duration":
return Duration(any)
return Duration(input.FromValue)
case "*time.Duration":
if _, ok := any.(*time.Duration); ok {
return any
if _, ok := input.FromValue.(*time.Duration); ok {
return input.FromValue
}
v := Duration(any)
v := Duration(input.FromValue)
return &v
case "map[string]string":
return MapStrStr(any)
return MapStrStr(input.FromValue)
case "map[string]interface{}":
return Map(any)
return Map(input.FromValue)
case "[]map[string]interface{}":
return Maps(any)
//case "gvar.Var":
// // TODO remove reflect usage to create gvar.Var, considering using unsafe pointer
// rv := reflect.New(intstore.ReflectTypeVarImp)
// ri := rv.Interface()
// if v, ok := ri.(apiSet); ok {
// v.Set(any)
// } else if v, ok := ri.(apiUnmarshalValue); ok {
// v.UnmarshalValue(any)
// } else {
// rv.Set(reflect.ValueOf(any))
// }
// return ri
return Maps(input.FromValue)
default:
return any
if input.ReferValue != nil {
var (
referReflectValue reflect.Value
)
if v, ok := input.ReferValue.(reflect.Value); ok {
referReflectValue = v
} else {
referReflectValue = reflect.ValueOf(input.ReferValue)
}
input.ToTypeName = referReflectValue.Kind().String()
input.ReferValue = nil
return doConvert(input)
}
return input.FromValue
}
}
// Convert converts the variable `fromValue` to the type `toTypeName`, the type `toTypeName` is specified by string.
// The optional parameter `extraParams` is used for additional necessary parameter for this conversion.
// It supports common types conversion as its conversion based on type name string.
func Convert(fromValue interface{}, toTypeName string, extraParams ...interface{}) interface{} {
return doConvert(doConvertInput{
FromValue: fromValue,
ToTypeName: toTypeName,
ReferValue: nil,
Extra: extraParams,
})
}
// Byte converts `any` to byte.
func Byte(any interface{}) byte {
if v, ok := any.(byte); ok {

View File

@ -166,7 +166,7 @@ func doMapConvert(value interface{}, recursive bool, tags ...string) map[string]
dataMap[String(reflectValue.Index(i).Interface())] = nil
}
}
case reflect.Map, reflect.Struct:
case reflect.Map, reflect.Struct, reflect.Interface:
convertedValue := doMapConvertForMapOrStructValue(true, value, recursive, newTags...)
if m, ok := convertedValue.(map[string]interface{}); ok {
return m

View File

@ -32,6 +32,7 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string)
switch pointerElemKind {
case reflect.Map:
return MapToMap(params, pointer, mapping...)
case reflect.Array, reflect.Slice:
var (
sliceElem = pointerElem.Elem()

View File

@ -107,6 +107,7 @@ func doStruct(params interface{}, pointer interface{}, mapping map[string]string
var (
paramsReflectValue reflect.Value
paramsInterface interface{} // DO NOT use `params` directly as it might be type of `reflect.Value`
pointerReflectValue reflect.Value
pointerReflectKind reflect.Kind
pointerElemReflectValue reflect.Value // The pointed element.
@ -116,6 +117,7 @@ func doStruct(params interface{}, pointer interface{}, mapping map[string]string
} else {
paramsReflectValue = reflect.ValueOf(params)
}
paramsInterface = paramsReflectValue.Interface()
if v, ok := pointer.(reflect.Value); ok {
pointerReflectValue = v
pointerElemReflectValue = v
@ -139,7 +141,7 @@ func doStruct(params interface{}, pointer interface{}, mapping map[string]string
}
// Normal unmarshalling interfaces checks.
if err, ok := bindVarToReflectValueWithInterfaceCheck(pointerReflectValue, params); ok {
if err, ok := bindVarToReflectValueWithInterfaceCheck(pointerReflectValue, paramsInterface); ok {
return err
}
@ -154,7 +156,7 @@ func doStruct(params interface{}, pointer interface{}, mapping map[string]string
// return v.UnmarshalValue(params)
//}
// Note that it's `pointerElemReflectValue` here not `pointerReflectValue`.
if err, ok := bindVarToReflectValueWithInterfaceCheck(pointerElemReflectValue, params); ok {
if err, ok := bindVarToReflectValueWithInterfaceCheck(pointerElemReflectValue, paramsInterface); ok {
return err
}
// Retrieve its element, may be struct at last.
@ -163,7 +165,7 @@ func doStruct(params interface{}, pointer interface{}, mapping map[string]string
// paramsMap is the map[string]interface{} type variable for params.
// DO NOT use MapDeep here.
paramsMap := Map(params)
paramsMap := Map(paramsInterface)
if paramsMap == nil {
return gerror.Newf("convert params to map failed: %v", params)
}
@ -304,7 +306,7 @@ func bindVarToStructAttr(elem reflect.Value, name string, value interface{}, map
return nil
}
defer func() {
if e := recover(); e != nil {
if exception := recover(); exception != nil {
if err = bindVarToReflectValue(structFieldValue, value, mapping, priorityTag); err != nil {
err = gerror.Wrapf(err, `error binding value to attribute "%s"`, name)
}
@ -314,7 +316,13 @@ func bindVarToStructAttr(elem reflect.Value, name string, value interface{}, map
if empty.IsNil(value) {
structFieldValue.Set(reflect.Zero(structFieldValue.Type()))
} else {
structFieldValue.Set(reflect.ValueOf(Convert(value, structFieldValue.Type().String())))
structFieldValue.Set(reflect.ValueOf(doConvert(
doConvertInput{
FromValue: value,
ToTypeName: structFieldValue.Type().String(),
ReferValue: structFieldValue,
},
)))
}
return nil
}
@ -335,9 +343,11 @@ func bindVarToReflectValueWithInterfaceCheck(reflectValue reflect.Value, value i
}
pointer = reflectValue.Interface()
}
// UnmarshalValue.
if v, ok := pointer.(apiUnmarshalValue); ok {
return v.UnmarshalValue(value), ok
}
// UnmarshalText.
if v, ok := pointer.(apiUnmarshalText); ok {
if s, ok := value.(string); ok {
return v.UnmarshalText([]byte(s)), ok
@ -450,11 +460,12 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma
default:
defer func() {
if e := recover(); e != nil {
if exception := recover(); exception != nil {
err = gerror.New(
fmt.Sprintf(`cannot convert value "%+v" to type "%s"`,
fmt.Sprintf(`cannot convert value "%+v" to type "%s":%+v`,
value,
structFieldValue.Type().String(),
exception,
),
)
}

View File

@ -100,13 +100,34 @@ func doStructs(params interface{}, pointer interface{}, mapping map[string]strin
}
}
// Converting `params` to map slice.
paramsMaps := Maps(params)
var (
paramsList []interface{}
paramsRv = reflect.ValueOf(params)
paramsKind = paramsRv.Kind()
)
for paramsKind == reflect.Ptr {
paramsRv = paramsRv.Elem()
paramsKind = paramsRv.Kind()
}
switch paramsKind {
case reflect.Slice, reflect.Array:
paramsList = make([]interface{}, paramsRv.Len())
for i := 0; i < paramsRv.Len(); i++ {
paramsList[i] = paramsRv.Index(i)
}
default:
var paramsMaps = Maps(params)
paramsList = make([]interface{}, len(paramsMaps))
for i := 0; i < len(paramsMaps); i++ {
paramsList[i] = paramsMaps[i]
}
}
// If `params` is an empty slice, no conversion.
if len(paramsMaps) == 0 {
if len(paramsList) == 0 {
return nil
}
var (
reflectElemArray = reflect.MakeSlice(pointerRv.Type().Elem(), len(paramsMaps), len(paramsMaps))
reflectElemArray = reflect.MakeSlice(pointerRv.Type().Elem(), len(paramsList), len(paramsList))
itemType = reflectElemArray.Index(0).Type()
itemTypeKind = itemType.Kind()
pointerRvElem = pointerRv.Elem()
@ -114,7 +135,7 @@ func doStructs(params interface{}, pointer interface{}, mapping map[string]strin
)
if itemTypeKind == reflect.Ptr {
// Pointer element.
for i := 0; i < len(paramsMaps); i++ {
for i := 0; i < len(paramsList); i++ {
var tempReflectValue reflect.Value
if i < pointerRvLength {
// Might be nil.
@ -123,21 +144,21 @@ func doStructs(params interface{}, pointer interface{}, mapping map[string]strin
if !tempReflectValue.IsValid() {
tempReflectValue = reflect.New(itemType.Elem()).Elem()
}
if err = doStruct(paramsMaps[i], tempReflectValue, mapping, priorityTag); err != nil {
if err = doStruct(paramsList[i], tempReflectValue, mapping, priorityTag); err != nil {
return err
}
reflectElemArray.Index(i).Set(tempReflectValue.Addr())
}
} else {
// Struct element.
for i := 0; i < len(paramsMaps); i++ {
for i := 0; i < len(paramsList); i++ {
var tempReflectValue reflect.Value
if i < pointerRvLength {
tempReflectValue = pointerRvElem.Index(i)
} else {
tempReflectValue = reflect.New(itemType).Elem()
}
if err = doStruct(paramsMaps[i], tempReflectValue, mapping, priorityTag); err != nil {
if err = doStruct(paramsList[i], tempReflectValue, mapping, priorityTag); err != nil {
return err
}
reflectElemArray.Index(i).Set(tempReflectValue)

View File

@ -58,7 +58,7 @@ func Test_Scan_StructStructs(t *testing.T) {
}
)
err := gconv.Scan(params, &users)
t.Assert(err, nil)
t.AssertNil(err)
t.Assert(users, g.Slice{
&User{
Uid: 1,