mirror of
https://gitee.com/johng/gf
synced 2026-06-07 18:26:02 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f63747e876 | |||
| 2854daded6 |
@ -2,7 +2,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
@ -20,9 +19,8 @@ type cFix struct {
|
||||
}
|
||||
|
||||
type cFixInput struct {
|
||||
g.Meta `name:"fix"`
|
||||
Path string `name:"path" short:"p" brief:"directory path, it uses current working directory in default"`
|
||||
Version string `name:"version" short:"v" brief:"custom specified version to fix, leave it empty to auto detect"`
|
||||
g.Meta `name:"fix"`
|
||||
Path string `name:"path" brief:"directory path, it uses current working directory in default"`
|
||||
}
|
||||
|
||||
type cFixOutput struct{}
|
||||
@ -33,45 +31,38 @@ type cFixItem struct {
|
||||
}
|
||||
|
||||
func (c cFix) Index(ctx context.Context, in cFixInput) (out *cFixOutput, err error) {
|
||||
|
||||
mlog.Print(`start auto fixing...`)
|
||||
defer mlog.Print(`done!`)
|
||||
if in.Path == "" {
|
||||
in.Path = gfile.Pwd()
|
||||
}
|
||||
if in.Version == "" {
|
||||
in.Version, err = c.autoDetectVersion(in)
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
if in.Version == "" {
|
||||
mlog.Print(`no GoFrame usage found, exit fixing`)
|
||||
return
|
||||
}
|
||||
mlog.Debugf(`current GoFrame version auto detect "%s"`, in.Version)
|
||||
}
|
||||
|
||||
if !gproc.IsChild() {
|
||||
mlog.Printf(`start auto fixing directory path "%s"...`, in.Path)
|
||||
defer mlog.Print(`done!`)
|
||||
}
|
||||
|
||||
err = c.doFix(in)
|
||||
return
|
||||
}
|
||||
|
||||
func (c cFix) doFix(in cFixInput) (err error) {
|
||||
version, err := c.getVersion(in)
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
if version == "" {
|
||||
mlog.Print(`no GoFrame usage found, exit fixing`)
|
||||
return
|
||||
}
|
||||
mlog.Debugf(`current GoFrame version found "%s"`, version)
|
||||
|
||||
var items = []cFixItem{
|
||||
{Version: "v2.3", Func: c.doFixV23},
|
||||
}
|
||||
for _, item := range items {
|
||||
if gstr.CompareVersionGo(in.Version, item.Version) < 0 {
|
||||
if gstr.CompareVersionGo(version, item.Version) < 0 {
|
||||
mlog.Debugf(
|
||||
`current GoFrame or contrib package version "%s" is lesser than "%s", nothing to do`,
|
||||
in.Version, item.Version,
|
||||
`current GoFrame version "%s" is lesser than "%s", nothing to do`,
|
||||
version, item.Version,
|
||||
)
|
||||
continue
|
||||
}
|
||||
if err = item.Func(in.Version); err != nil {
|
||||
if err = item.Func(version); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -96,7 +87,7 @@ func (c cFix) doFixV23(version string) error {
|
||||
return gfile.ReplaceDirFunc(replaceFunc, ".", "*.go", true)
|
||||
}
|
||||
|
||||
func (c cFix) autoDetectVersion(in cFixInput) (string, error) {
|
||||
func (c cFix) getVersion(in cFixInput) (string, error) {
|
||||
var (
|
||||
err error
|
||||
path = gfile.Join(in.Path, "go.mod")
|
||||
|
||||
@ -3,9 +3,6 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"runtime"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -29,7 +26,7 @@ const (
|
||||
gf up
|
||||
gf up -a
|
||||
gf up -c
|
||||
gf up -cf
|
||||
gf up -f -c
|
||||
`
|
||||
)
|
||||
|
||||
@ -42,8 +39,8 @@ func init() {
|
||||
type cUpInput struct {
|
||||
g.Meta `name:"up" config:"gfcli.up"`
|
||||
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
|
||||
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool" orphan:"true"`
|
||||
Fix bool `name:"fix" short:"f" brief:"auto fix codes(it only make sense if cli is to be upgraded)" orphan:"true"`
|
||||
Fix bool `name:"fix" short:"f" brief:"auto fix codes" orphan:"true"`
|
||||
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool (not supported yet)" orphan:"true"`
|
||||
}
|
||||
|
||||
type cUpOutput struct{}
|
||||
@ -51,72 +48,42 @@ type cUpOutput struct{}
|
||||
func (c cUp) Index(ctx context.Context, in cUpInput) (out *cUpOutput, err error) {
|
||||
defer func() {
|
||||
if err == nil {
|
||||
mlog.Print()
|
||||
mlog.Print(`👏congratulations! you've upgraded to the latest version of GoFrame! enjoy it!👏`)
|
||||
mlog.Print()
|
||||
mlog.Print(`done!`)
|
||||
}
|
||||
}()
|
||||
|
||||
var doUpgradeVersionOut *doUpgradeVersionOutput
|
||||
if in.All {
|
||||
in.Cli = true
|
||||
in.Fix = true
|
||||
}
|
||||
if doUpgradeVersionOut, err = c.doUpgradeVersion(ctx, in); err != nil {
|
||||
if err = c.doUpgradeVersion(ctx, in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if in.Cli {
|
||||
if err = c.doUpgradeCLI(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if in.Cli && in.Fix {
|
||||
if doUpgradeVersionOut != nil && len(doUpgradeVersionOut.Items) > 0 {
|
||||
upgradedPathSet := gset.NewStrSet()
|
||||
for _, item := range doUpgradeVersionOut.Items {
|
||||
if !upgradedPathSet.AddIfNotExist(item.DirPath) {
|
||||
continue
|
||||
}
|
||||
if err = c.doAutoFixing(ctx, item.DirPath, item.Version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//if in.Cli {
|
||||
// if err = c.doUpgradeCLI(ctx); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//}
|
||||
return
|
||||
}
|
||||
|
||||
type doUpgradeVersionOutput struct {
|
||||
Items []doUpgradeVersionOutputItem
|
||||
}
|
||||
|
||||
type doUpgradeVersionOutputItem struct {
|
||||
DirPath string
|
||||
Version string
|
||||
}
|
||||
|
||||
func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeVersionOutput, err error) {
|
||||
func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (err error) {
|
||||
mlog.Print(`start upgrading version...`)
|
||||
out = &doUpgradeVersionOutput{
|
||||
Items: make([]doUpgradeVersionOutputItem, 0),
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
Name string
|
||||
Version string
|
||||
}
|
||||
|
||||
var (
|
||||
temp string
|
||||
dirPath = gfile.Pwd()
|
||||
goModPath = gfile.Join(dirPath, "go.mod")
|
||||
dir = gfile.Pwd()
|
||||
temp string
|
||||
path = gfile.Join(dir, "go.mod")
|
||||
)
|
||||
// It recursively upgrades the go.mod from sub folder to its parent folders.
|
||||
for {
|
||||
if gfile.Exists(goModPath) {
|
||||
if gfile.Exists(path) {
|
||||
var packages []Package
|
||||
err = gfile.ReadLines(goModPath, func(line string) error {
|
||||
err = gfile.ReadLines(path, func(line string) error {
|
||||
line = gstr.Trim(line)
|
||||
if gstr.HasPrefix(line, gfPackage) {
|
||||
array := gstr.SplitAndTrim(line, " ")
|
||||
@ -132,76 +99,38 @@ func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeV
|
||||
}
|
||||
for _, pkg := range packages {
|
||||
mlog.Printf(`upgrading "%s" from "%s" to "latest"`, pkg.Name, pkg.Version)
|
||||
// go get -u
|
||||
command := fmt.Sprintf(`cd %s && go get -u %s@latest`, dirPath, pkg.Name)
|
||||
command := fmt.Sprintf(`go get -u %s@latest`, pkg.Name)
|
||||
if err = gproc.ShellRun(ctx, command); err != nil {
|
||||
return
|
||||
}
|
||||
// go mod tidy
|
||||
if err = utils.GoModTidy(ctx, dirPath); err != nil {
|
||||
return nil, err
|
||||
mlog.Print()
|
||||
}
|
||||
if in.Fix {
|
||||
if err = c.doAutoFixing(ctx, dir); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Items = append(out.Items, doUpgradeVersionOutputItem{
|
||||
DirPath: dirPath,
|
||||
Version: pkg.Version,
|
||||
})
|
||||
mlog.Print()
|
||||
}
|
||||
return
|
||||
}
|
||||
temp = gfile.Dir(dirPath)
|
||||
if temp == "" || temp == dirPath {
|
||||
temp = gfile.Dir(dir)
|
||||
if temp == "" || temp == dir {
|
||||
return
|
||||
}
|
||||
dirPath = temp
|
||||
goModPath = gfile.Join(dirPath, "go.mod")
|
||||
dir = temp
|
||||
path = gfile.Join(dir, "go.mod")
|
||||
}
|
||||
}
|
||||
|
||||
// doUpgradeCLI downloads the new version binary with process.
|
||||
func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
|
||||
mlog.Print(`start upgrading cli...`)
|
||||
var (
|
||||
downloadUrl = fmt.Sprintf(
|
||||
`https://github.com/gogf/gf/releases/latest/download/gf_%s_%s`,
|
||||
runtime.GOOS, runtime.GOARCH,
|
||||
)
|
||||
localSaveFilePath = gfile.SelfPath() + "~"
|
||||
)
|
||||
mlog.Printf(`start downloading "%s" to "%s", it may take some time`, downloadUrl, localSaveFilePath)
|
||||
err = utils.HTTPDownloadFileWithPercent(downloadUrl, localSaveFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
mlog.Printf(`new version cli binary is successfully installed to "%s"`, gfile.SelfPath())
|
||||
mlog.Printf(`remove temporary buffer file "%s"`, localSaveFilePath)
|
||||
_ = gfile.Remove(localSaveFilePath)
|
||||
}()
|
||||
|
||||
// It fails if file not exist or its size is less than 1MB.
|
||||
if !gfile.Exists(localSaveFilePath) || gfile.Size(localSaveFilePath) < 1024*1024 {
|
||||
mlog.Fatalf(`download "%s" to "%s" failed`, downloadUrl, localSaveFilePath)
|
||||
}
|
||||
|
||||
// It replaces self binary with new version cli binary.
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
if err := gfile.Rename(localSaveFilePath, gfile.SelfPath()); err != nil {
|
||||
mlog.Fatalf(`install failed: %s`, err.Error())
|
||||
}
|
||||
|
||||
default:
|
||||
if err := gfile.PutBytes(gfile.SelfPath(), gfile.GetBytes(localSaveFilePath)); err != nil {
|
||||
mlog.Fatalf(`install failed: %s`, err.Error())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c cUp) doAutoFixing(ctx context.Context, dirPath string, version string) (err error) {
|
||||
mlog.Printf(`auto fixing directory path "%s" from version "%s" ...`, dirPath, version)
|
||||
command := fmt.Sprintf(`gf fix -p %s`, dirPath)
|
||||
_ = gproc.ShellRun(ctx, command)
|
||||
func (c cUp) doAutoFixing(ctx context.Context, dirPath string) (err error) {
|
||||
mlog.Printf(`auto fixing path "%s"...`, dirPath)
|
||||
err = cFix{}.doFix(cFixInput{
|
||||
Path: dirPath,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"golang.org/x/tools/imports"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// GoFmt formats the source file and adds or removes import statements as necessary.
|
||||
@ -38,13 +36,6 @@ func GoFmt(path string) {
|
||||
}
|
||||
}
|
||||
|
||||
// GoModTidy executes `go mod tidy` at specified directory `dirPath`.
|
||||
func GoModTidy(ctx context.Context, dirPath string) error {
|
||||
command := fmt.Sprintf(`cd %s && go mod tidy`, dirPath)
|
||||
err := gproc.ShellRun(ctx, command)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsFileDoNotEdit checks and returns whether file contains `do not edit` key.
|
||||
func IsFileDoNotEdit(filePath string) bool {
|
||||
if !gfile.Exists(filePath) {
|
||||
|
||||
@ -1,98 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// HTTPDownloadFileWithPercent downloads target url file to local path with percent process printing.
|
||||
func HTTPDownloadFileWithPercent(url string, localSaveFilePath string) error {
|
||||
start := time.Now()
|
||||
out, err := os.Create(localSaveFilePath)
|
||||
if err != nil {
|
||||
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
headResp, err := http.Head(url)
|
||||
if err != nil {
|
||||
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
|
||||
}
|
||||
defer headResp.Body.Close()
|
||||
|
||||
size, err := strconv.Atoi(headResp.Header.Get("Content-Length"))
|
||||
if err != nil {
|
||||
return gerror.Wrap(err, "retrieve Content-Length failed")
|
||||
}
|
||||
doneCh := make(chan int64)
|
||||
|
||||
go doPrintDownloadPercent(doneCh, localSaveFilePath, int64(size))
|
||||
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
wroteBytesCount, err := io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
|
||||
}
|
||||
|
||||
doneCh <- wroteBytesCount
|
||||
elapsed := time.Since(start)
|
||||
if elapsed > time.Minute {
|
||||
mlog.Printf(`download completed in %.0fm`, float64(elapsed)/float64(time.Minute))
|
||||
} else {
|
||||
mlog.Printf(`download completed in %.0fs`, elapsed.Seconds())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func doPrintDownloadPercent(doneCh chan int64, localSaveFilePath string, total int64) {
|
||||
var (
|
||||
stop = false
|
||||
lastPercentFmt string
|
||||
)
|
||||
for {
|
||||
select {
|
||||
case <-doneCh:
|
||||
stop = true
|
||||
|
||||
default:
|
||||
file, err := os.Open(localSaveFilePath)
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
fi, err := file.Stat()
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
size := fi.Size()
|
||||
if size == 0 {
|
||||
size = 1
|
||||
}
|
||||
var (
|
||||
percent = float64(size) / float64(total) * 100
|
||||
percentFmt = fmt.Sprintf(`%.0f`, percent) + "%"
|
||||
)
|
||||
if lastPercentFmt != percentFmt {
|
||||
lastPercentFmt = percentFmt
|
||||
mlog.Print(percentFmt)
|
||||
}
|
||||
}
|
||||
|
||||
if stop {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
@ -9,11 +9,8 @@ package mysql_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
"github.com/gogf/gf/v2/util/gmeta"
|
||||
)
|
||||
|
||||
func Test_Model_Builder(t *testing.T) {
|
||||
@ -62,66 +59,4 @@ func Test_Model_Builder(t *testing.T) {
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(all), 6)
|
||||
})
|
||||
|
||||
// Where with struct which has a field type of *gtime.Time
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := db.Model(table)
|
||||
b := m.Builder()
|
||||
|
||||
type Query struct {
|
||||
Id interface{}
|
||||
Nickname *gtime.Time
|
||||
}
|
||||
|
||||
where, args := b.Where(&Query{Id: 1}).Build()
|
||||
t.Assert(where, "`id`=? AND `nickname` IS NULL")
|
||||
t.Assert(args, []interface{}{1})
|
||||
})
|
||||
|
||||
// Where with struct which has a field type of *gjson.Json
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := db.Model(table)
|
||||
b := m.Builder()
|
||||
|
||||
type Query struct {
|
||||
Id interface{}
|
||||
Nickname *gjson.Json
|
||||
}
|
||||
|
||||
where, args := b.Where(&Query{Id: 1}).Build()
|
||||
t.Assert(where, "`id`=? AND `nickname` IS NULL")
|
||||
t.Assert(args, []interface{}{1})
|
||||
})
|
||||
|
||||
// Where with do struct which has a field type of *gtime.Time and generated by gf cli
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := db.Model(table)
|
||||
b := m.Builder()
|
||||
|
||||
type Query struct {
|
||||
gmeta.Meta `orm:"do:true"`
|
||||
Id interface{}
|
||||
Nickname *gtime.Time
|
||||
}
|
||||
|
||||
where, args := b.Where(&Query{Id: 1}).Build()
|
||||
t.Assert(where, "`id`=?")
|
||||
t.Assert(args, []interface{}{1})
|
||||
})
|
||||
|
||||
// Where with do struct which has a field type of *gjson.Json and generated by gf cli
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
m := db.Model(table)
|
||||
b := m.Builder()
|
||||
|
||||
type Query struct {
|
||||
gmeta.Meta `orm:"do:true"`
|
||||
Id interface{}
|
||||
Nickname *gjson.Json
|
||||
}
|
||||
|
||||
where, args := b.Where(&Query{Id: 1}).Build()
|
||||
t.Assert(where, "`id`=?")
|
||||
t.Assert(args, []interface{}{1})
|
||||
})
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/internal/empty"
|
||||
"github.com/gogf/gf/v2/internal/reflection"
|
||||
"github.com/gogf/gf/v2/internal/utils"
|
||||
@ -211,7 +210,7 @@ func DataToMapDeep(value interface{}) map[string]interface{} {
|
||||
m := gconv.Map(value, structTagPriority...)
|
||||
for k, v := range m {
|
||||
switch v.(type) {
|
||||
case time.Time, *time.Time, gtime.Time, *gtime.Time, gjson.Json, *gjson.Json:
|
||||
case time.Time, *time.Time, gtime.Time, *gtime.Time:
|
||||
m[k] = v
|
||||
|
||||
default:
|
||||
|
||||
@ -45,58 +45,56 @@ func TestSafeMutex(t *testing.T) {
|
||||
go func() {
|
||||
safeLock.Lock()
|
||||
array.Append(1)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
array.Append(1)
|
||||
safeLock.Unlock()
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
safeLock.Lock()
|
||||
array.Append(1)
|
||||
time.Sleep(2000 * time.Millisecond)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
array.Append(1)
|
||||
safeLock.Unlock()
|
||||
}()
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
t.Assert(array.Len(), 1)
|
||||
time.Sleep(800 * time.Millisecond)
|
||||
time.Sleep(80 * time.Millisecond)
|
||||
t.Assert(array.Len(), 3)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
t.Assert(array.Len(), 3)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
t.Assert(array.Len(), 4)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUnsafeMutex(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
unsafeLock = mutex.New()
|
||||
array = garray.New(true)
|
||||
)
|
||||
unsafeLock := mutex.New()
|
||||
array := garray.New(true)
|
||||
|
||||
go func() {
|
||||
unsafeLock.Lock()
|
||||
array.Append(1)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
array.Append(1)
|
||||
unsafeLock.Unlock()
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
unsafeLock.Lock()
|
||||
array.Append(1)
|
||||
time.Sleep(2000 * time.Millisecond)
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
array.Append(1)
|
||||
unsafeLock.Unlock()
|
||||
}()
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
t.Assert(array.Len(), 2)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
t.Assert(array.Len(), 3)
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
t.Assert(array.Len(), 3)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
t.Assert(array.Len(), 4)
|
||||
})
|
||||
}
|
||||
|
||||
@ -407,7 +407,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
|
||||
array[arrayIndex] = doMapConvertForMapOrStructValue(
|
||||
doMapConvertForMapOrStructValueInput{
|
||||
IsRoot: false,
|
||||
Value: rvAttrField.Index(arrayIndex).Interface(),
|
||||
Value: rvAttrField.Index(arrayIndex),
|
||||
RecursiveType: in.RecursiveType,
|
||||
RecursiveOption: in.RecursiveType == recursiveTypeTrue,
|
||||
Tags: in.Tags,
|
||||
@ -463,7 +463,7 @@ func doMapConvertForMapOrStructValue(in doMapConvertForMapOrStructValueInput) in
|
||||
for i := 0; i < length; i++ {
|
||||
array[i] = doMapConvertForMapOrStructValue(doMapConvertForMapOrStructValueInput{
|
||||
IsRoot: false,
|
||||
Value: reflectValue.Index(i).Interface(),
|
||||
Value: reflectValue.Index(i),
|
||||
RecursiveType: in.RecursiveType,
|
||||
RecursiveOption: in.RecursiveType == recursiveTypeTrue,
|
||||
Tags: in.Tags,
|
||||
|
||||
@ -125,6 +125,9 @@ func Interfaces(any interface{}) []interface{} {
|
||||
return slice
|
||||
|
||||
default:
|
||||
if originValueAndKind.OriginValue.IsZero() {
|
||||
return []interface{}{}
|
||||
}
|
||||
return []interface{}{any}
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,55 +223,3 @@ func Test_Issue2381(t *testing.T) {
|
||||
t.Assert(a1.Flag.String(), a2.Flag.String())
|
||||
})
|
||||
}
|
||||
|
||||
// https://github.com/gogf/gf/issues/2391
|
||||
func Test_Issue2391(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type Inherit struct {
|
||||
Ids []int
|
||||
Ids2 []int64
|
||||
Flag *gjson.Json
|
||||
Title string
|
||||
}
|
||||
|
||||
type Test1 struct {
|
||||
Inherit
|
||||
}
|
||||
type Test2 struct {
|
||||
Inherit
|
||||
}
|
||||
|
||||
var (
|
||||
a1 Test1
|
||||
a2 Test2
|
||||
)
|
||||
|
||||
a1 = Test1{
|
||||
Inherit{
|
||||
Ids: []int{1, 2, 3},
|
||||
Ids2: []int64{4, 5, 6},
|
||||
Flag: gjson.New("[\"1\", \"2\"]"),
|
||||
Title: "测试",
|
||||
},
|
||||
}
|
||||
|
||||
err := gconv.Scan(a1, &a2)
|
||||
t.AssertNil(err)
|
||||
t.Assert(a1.Ids, a2.Ids)
|
||||
t.Assert(a1.Ids2, a2.Ids2)
|
||||
t.Assert(a1.Title, a2.Title)
|
||||
t.Assert(a1.Flag.String(), a2.Flag.String())
|
||||
})
|
||||
}
|
||||
|
||||
// https://github.com/gogf/gf/issues/2395
|
||||
func Test_Issue2395(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type Test struct {
|
||||
Num int
|
||||
}
|
||||
var ()
|
||||
obj := Test{Num: 0}
|
||||
t.Assert(gconv.Interfaces(obj), []interface{}{obj})
|
||||
})
|
||||
}
|
||||
|
||||
@ -298,7 +298,7 @@ func Test_Slice_Empty(t *testing.T) {
|
||||
t.Assert(gconv.Strings(nil), nil)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.AssertEQ(gconv.SliceAny(""), []interface{}{""})
|
||||
t.AssertEQ(gconv.SliceAny(""), []interface{}{})
|
||||
t.Assert(gconv.SliceAny(nil), nil)
|
||||
})
|
||||
}
|
||||
|
||||
@ -2,5 +2,5 @@ package gf
|
||||
|
||||
const (
|
||||
// VERSION is the current GoFrame version.
|
||||
VERSION = "v2.3.1"
|
||||
VERSION = "v2.3.0"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user