Code Monkey home page Code Monkey logo

gookit / goutil Goto Github PK

View Code? Open in Web Editor NEW
1.8K 31.0 176.0 2.6 MB

💪 Helper Utils(700+): int, byte, string, array/slice, map, struct, dump, convert/format, error, web/http, cli/flag, OS/ENV, filesystem, system, test/assert, time and more. Go 常用的一些工具函数:数字,字符串,数组,Map,结构体,反射,文本,文件,错误,时间日期,特殊处理,格式化,常用信息获取等等

Home Page: https://pkg.go.dev/github.com/gookit/goutil

License: MIT License

Go 99.83% Makefile 0.13% Smarty 0.04%
utils go-library tools strings cli-utilities dumper golang utilities go-utils string

goutil's People

Contributors

ah-its-andy avatar aoranallen avatar boynchan avatar bsiegert avatar cokebeer avatar creky avatar dependabot-preview[bot] avatar dependabot[bot] avatar everywan avatar guanhui07 avatar huangkuan123 avatar inhere avatar juneezee avatar pigwantacat avatar quetzyg avatar reyoung avatar telanflow avatar tim1116 avatar uptutu avatar xiaok29 avatar xiaozuo7 avatar yanghx-git avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

goutil's Issues

[Question] Any ``Func`` Equivalent to This?

Trying to find a util function equivalent to this:

// Check if value is zero of its type. string => "", number => 0, pointer => nil, etc...
reflect.ValueOf(anyVal).IsZero()

Can you point me to the right one?
Thanks

ToBool function from internal

System (please complete the following information):

  • OS: x86_64 x86_64 x86_64 GNU/Linux
  • GO Version: go version go1.21.4 linux/amd64
  • Pkg Version: 0.6.12

Describe the suggestion

You put function ToBool which gets any as an argument to internal directory. I need exactly this function. Not string as input parameter but any. Please take this function out of internal directory that I'll have possibility to use it in project.

Supports for slices in mapuitl.go

I've been seeing and developing an improvement so that the GetByPath function supports access to slice structures.

I added the following tests in TestGetByPath and they pass successfully.

        //...

        v, ok = maputil.GetByPath("key2", mp)
	assert.True(t, ok)
	assert.Equal(t, mp["key2"], v)

	v, ok = maputil.GetByPath("key2.0", mp)
	assert.True(t, ok)
	assert.Equal(t, "sv1", v)

	v, ok = maputil.GetByPath("key2.1", mp)
	assert.True(t, ok)
	assert.Equal(t, "sv2", v)

	v, ok = maputil.GetByPath("key4.0", mp)
	assert.True(t, ok)
	assert.Equal(t, 1, v)

	v, ok = maputil.GetByPath("key4.1", mp)
	assert.True(t, ok)
	assert.Equal(t, 2, v)

	v, ok = maputil.GetByPath("key5.0", mp)
	assert.True(t, ok)
	assert.Equal(t, 1, v)

	v, ok = maputil.GetByPath("key5.1", mp)
	assert.True(t, ok)
	assert.Equal(t, "2", v)

	v, ok = maputil.GetByPath("key5.2", mp)
	assert.True(t, ok)
	assert.Equal(t, true, v)

	// Out of bound value
	v, ok = maputil.GetByPath("key2.2", mp)
	assert.False(t, ok)
	assert.Nil(t, v)

        //...

Concurrency issues in Dumper

System (please complete the following information):

  • OS: linux, macOS
  • GO Version: 1.18
  • Pkg Version: 0.5.5

Describe the bug

&fatal error: concurrent map read and map write


To see all goroutines, visit https://github.com/maruel/panicparse#gotraceback

1: running
    runtime :0 throw()
runtime.throw({0x10490cd05, 0x21})
        /usr/local/go/src/runtime/panic.go:1198 +0x54 fp=0x140003dfa70 sp=0x140003dfa40 pc=0x1046d9c34
runtime.mapaccess2(0x104997d80, 0x1400044c3f0, 0x140003dfaf0)
        /usr/local/go/src/runtime/map.go:469 +0x228 fp=0x140003dfab0 sp=0x140003dfa70 pc=0x1046b31f8
github.com/gookit/goutil/dump.(*Dumper).checkCyclicRef(0x14000146180, {0x1049f0bd0, 0x1049d2980}, {0x1049d2980, 0x14000384420, 0x199})
        /{$GOPATH}/pkg/mod/github.com/gookit/goutil@v0.5.5/dump/dumper.go:403 +0x6c fp=0x140003dfb30 sp=0x140003dfab0 pc=0x1047c8bcc
github.com/gookit/goutil/dump.(*Dumper).printRValue(0x14000146180, {0x1049f0bd0, 0x10497f860}, {0x10497f860, 0x14000384420, 0x16})
        /{$GOPATH}/pkg/mod/github.com/gookit/goutil@v0.5.5/dump/dumper.go:309 +0x121c fp=0x140003dfeb0 sp=0x140003dfb30 pc=0x1047c799c
github.com/gookit/goutil/dump.(*Dumper).printOne(0x14000146180, {0x10497f860, 0x14000384420})
        /{$GOPATH}/pkg/mod/github.com/gookit/goutil@v0.5.5/dump/dumper.go:229 +0x118 fp=0x140003dff30 sp=0x140003dfeb0 pc=0x1047c6718
github.com/gookit/goutil/dump.(*Dumper).dump(0x14000146180, {0x140003dffa8, 0x1, 0x1})
        /{$GOPATH}/pkg/mod/github.com/gookit/goutil@v0.5.5/dump/dumper.go:171 +0x120 fp=0x140003dff80 sp=0x140003dff30 pc=0x1047c5e20
github.com/gookit/goutil/dump.(*Dumper).Println(...)
        /{$GOPATH}/pkg/mod/github.com/gookit/goutil@v0.5.5/dump/dumper.go:136
github.com/gookit/goutil/dump.Println(...)
        /{$GOPATH}/pkg/mod/github.com/gookit/goutil@v0.5.5/dump/dump.go:96
main.(*SimpleTradeSpi).OnRtnTrade(0x104bdd850, 0x14000384420)
        /{$GOPATH}/sample/main.go:274 +0x5c fp=0x140003dffc0 sp=0x140003dff80 pc=0x10490021c
runtime.goexit()
        /usr/local/go/src/runtime/asm_arm64.s:1133 +Failed: failed to parse int on line: "runtime.throw({0x10490cd05, 0x21})"

出错位置:

func (d *Dumper) checkCyclicRef(t reflect.Type, v reflect.Value) (goon bool) {
	addr := v.UnsafeAddr()
	vis := visit{addr, t}

	if vd, ok := d.visited[vis]; ok && vd < d.MaxDepth { <------- here
		d.indentPrint(t.String(), "{(!CYCLIC REFERENCE!)}\n")
		return false // don't print v again
	}

	// record
	d.visited[vis] = d.curDepth
	return true
}

runtime error: makeslice: cap out of range

  • OS: linux
  • GO Version: 1.19.3
  • Pkg Version: 0.6.1

I use dump.Format(ob) where ob is an interface of struct
then I have error:
runtime error: makeslice: cap out of range

trace is:

Screenshot from 2022-12-25 15-12-24

终于找到有用的东西了,非常感谢

对于指针的数据,我找了挺久的一个dump库,非常容易用来print值,妈妈再也不用担心我的困扰了,当然还有其他的库我本身也经常用到这些功能,但是一直没有封装自己的库,看到你这个库我觉得挺好的

fsutil.ReadOrErr() 没有关闭流

System (please complete the following information):

  • OS: linux [e.g. linux, macOS]
  • GO Version: 1.21 [e.g. 1.13]
  • Pkg Version: 0.6.12 [e.g. 1.1.1]

Describe the bug

A clear and concise description of what the bug is.

To Reproduce

func ReadOrErr(in any) ([]byte, error) {
        // 传入字符串会读取文件,转换为 []byte 后,file 没有close 
	r, err := NewIOReader(in)
	if err != nil {
		return nil, err
	}
	return io.ReadAll(r)
}

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

Add any other context about the problem here.

cannot use AlignLeft (constant 1 of type strutil.PosFlag) as type uint8 in struct literal

System (please complete the following information):

  • OS: macOS 10.15
  • GO Version: go1.18.4 darwin/amd64
  • Pkg Version:
    • github.com/gookit/gcli/v2 v2.3.4
    • github.com/gookit/goutil v0.6.0 // indirect

Describe the bug

../../../../pkg/mod/github.com/gookit/gcli/[email protected]/app.go:100:18: cannot use AlignLeft (constant 1 of type strutil.PosFlag) as type uint8 in struct literal
../../../../pkg/mod/github.com/gookit/gcli/[email protected]/cmd.go:306:14: cannot use AlignLeft (constant 1 of type strutil.PosFlag) as type uint8 in struct literal
../../../../pkg/mod/github.com/gookit/gcli/[email protected]/gflag.go:503:60: cannot use fs.Alignment (variable of type uint8) as type strutil.PosFlag in argument to strutil.Padding

gookit/gocli ->app.go

func NewApp(fn ...func(a *App)) *App {
	app := &App{
		Args: os.Args,
		Name: "GCli App",
		Logo: Logo{Style: "info"},
		// set a default version
		Version: "1.0.0",
		// internal
		// cmdLine: CLI,
		core: core{
			cmdLine: CLI,
			gFlags: NewFlags("appGlobalOpts").WithOption(FlagsOption{
				WithoutType: true,
				NameDescOL:  true,
				Alignment:   AlignLeft,
				TagName:     FlagTagName,
			}),
		},
		// config
		ExitOnEnd: true,
		// commands
		commands: make(map[string]*Command),
		// group
		moduleCommands: make(map[string]map[string]*Command),
		// some default values
		nameMaxLen:  12,
		Description: "This is my CLI application",
	}

	if len(fn) > 0 {
		fn[0](app)
	}

	return app
}

gookit/gocli -> gflag.go

const (
	AlignLeft  = strutil.PosRight
	AlignRight = strutil.PosLeft
	// FlagTagName on struct
	FlagTagName = "flag"
	// default desc
	defaultDesc = "No description"
)

gookit/goutil ->padding.go

// PosFlag type
type PosFlag uint8

// Position for padding/resize string
const (
	PosLeft PosFlag = iota
	PosRight
	PosMiddle
)

[FEAT] Conversion Functions with Default Values?

Would be nice to have some utils to convert to a design data type, if error or not the same type then return the default vals:

I have a scenarios where I want to convert a float and want the value to be 0.0 if failed:

test := mathutil.QuietFloat(math.NaN) //=> test = NaN, I want it to always be a float type instead (0.0 if failed).

The idea...

utils.FloatOrDefault(in any, default float64)
test := utils.FloatOrDefault("test", 0.0) //=> Error, return test = 0.0

utils.StringOrDefault(in any, default string)
test := utils.StringOrDefault(nil, "hello") //=> Error, return test = "hello"

...

Something like that. you get the idea 🙂
Thanks,

arrutil.Excepts 差集,结果不正确

func TestExceptsShouldPassed(t *testing.T) {
data := []string{
"a",
"b",
"c",
}
result := arrutil.Excepts(data, []string{"a", "b"}, arrutil.StringEqualsComparer)
assert.Eq(t, []string{"c"}, result.([]string))
}

如上单元测试,改写 data 和 []string{"a", "b"} 顺序,不能正确取得slice的差集。

改成下方的单元测试,不能通过。

func TestExceptsShouldPassed(t *testing.T) {
	data := []string{
		"a",
		"b",
		"c",
	}
	result := arrutil.Excepts([]string{"a", "b"}, data, arrutil.StringEqualsComparer)
	assert.Eq(t, []string{"c"}, result.([]string))
}

Deleting Keys from Maps Using Dot Notation

I would like to delete a key from a nested map using "dot" notation. Is there a method to remove a nested key from a map?

obj := map[string]any{
	"name": "Desk",
	"new": map[string]any{
		"foo": "bar",
	},
}

Delete(obj, "new.foo")

// After deletion, the map should look like:
// obj = map[string]any{
// 	"name": "Desk",
// 	"new":  map[string]any{},
// }

// Delete the key "foo" from the nested map "new"

在windows平台下,编译报错

windows平台下,在使用github.com/gookit/color和github.com/gookit/gcli/v2/interact时 ,因为依赖了该包, 报了异常undefined sysutil.IsConsole, sysutil.IsMSys, sysutil.HasShellEnv,启用了go mod,我尝试删除了所有go mod缓存,并且重新编译,但还是报了上述错误。


查阅了源代码,发现sysutil/sysutil.go文件头部有条 // +build !windows 代码,表示winodws下该文件不会编译,是表示该包只能在非windows下使用吗?

Dump: Can dump provide a parameter to control nil/zero not to print?

Example:

type T1 struct {
	T2 *T2
	T3 *T3
}

type T2 struct {
	Name2 string
}

type T3 struct {
	Name3 string
}

func main() {
	t1 := &T1{
		T2: &T2{
			Name2: "xx",
		},
	}
	dump.P(t1)
}

output:

PRINT AT main.main(main.go:27)
&main.T1 {
  T2: &main.T2 {
    Name2: string("xx"), #len=2
  },
  T3: *main.T3<nil>,
}

i want to ignore T3: *main.T3<nil>

Correct way to embed JSON in a env var

Hi,

I'm having problems trying to embed a default JSON value for a env variable in my configuration file. Is this even allowed?

Config file:

test:
    credentials: >
        ${CREDENTIALS|{}}
    apiKey: ${API_KEY|AN_APIKEY}
    apiUri: ${API_URI|http://localhost:8888/v1/api}

Test program:

package main

import (
    "fmt"
	"google.golang.org/api/option"
	"github.com/gookit/config/v2"
	"github.com/gookit/config/v2/yamlv3"
)

type Setup struct {
	Credentials string `mapstructure:"credentials"`
	ApiKey      string `mapstructure:"apiKey"`
	ApiUri      string `mapstructure:"apiUri"`
}

type Configuration struct {
	Details Setup `mapstructure:"test"`
}

func main() {
	var st Configuration
	c := config.New("config")
	c.WithOptions(config.ParseEnv)
	c.AddDriver(yamlv3.Driver)

	err := c.LoadFiles("test.yml")
	if err != nil {
		panic(err)
	}

    c.Decode(&st)
	opt := option.WithCredentialsJSON([]byte(st.Details.Credentials))

    fmt.Printf("config creds: %s\n", opt)
}

It's adding an extra } at the end:

$ CREDENTIALS='{"type": "model"}' ./config
config creds: {"type": "model"}}
$ ./config
config creds: {}

Thanks.

Wrong logic for struts/writer.go line 143&103

Describe the bug

Affect file: github.com\gookit\[email protected]\structs\writer.go line 143 && 103

To Reproduce

for i := 0; i < rt.NumField(); i++{
if err := reflects.SetValue(fv, val); err != nil {
->line 143			return err
		}
}

Expected behavior

return err should be replace to continue.

Additional context
There is more fields in a sturct, we should process the next field if one field occured error in a loop, keep the error field default value.

[proposal] maputil add func diff(amap, bmap) return difference fields

A recent task was to compare two json strings and find the field that had been modified.

I converted them into two map[string]interface data and write a func diff(a, b map[string]interface{}) to find the changed fields.

I'd like PR this func to maputil later. hope it can help more people who need it.

Function RandomChars has bug

System (please complete the following information):

  • OS: windows
  • GO Version: 1.19
  • Pkg Version: v0.6.12

Describe the bug

Always get string like this: jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjpp, 11111eeeeeeeeeeeeeeeeeeeeeeeeeee

To Reproduce
Here is my code:

func TestRandStr(t *testing.T) {
	a := strutil.RandomCharsV2(32)
	t.Log(a)
}

Screenshots

image

Dot notation fails to access nested map keys containing "."

System (please complete the following information):

  • OS: linux
  • GO Version: 1.20
  • Pkg Version: 0.6.12

Describe the bug

When attempting to access nested map keys using dot notation, the functionality fails when the key contains a period (".") character. This issue prevents the retrieval of values from nested maps with keys containing periods.

To Reproduce

obj := map[string]any{
	"framework.developers": map[string]any{
		"name": "Krishan",
		"lang": "Golang",
	},
}
maputil.GetByPath("framework.developers.name", obj)
// output: <nil>, false
// expected: "Krishan", true

Expected behavior

The function maputil.GetByPath should successfully retrieve the value associated with the key "name" within the nested map framework.developers. The expected behavior is to retrieve the value Krishan using the provided path.

filter中的str2time的问题

package main

import (
	"fmt"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/gookit/goutil/dump"
	"github.com/gookit/validate"
)

func main() {
	binding.Validator = &customValidator{}
	r := gin.Default()
	r.POST("/user/list", func(ctx *gin.Context) {
		var user User
		err := ctx.ShouldBindJSON(&user)
		if err != nil {
			dump.P(err)
			ctx.String(400, "出错"+err.Error())
			return
		}
		ctx.String(200, fmt.Sprintf("验证通过:%v", user.Time))
	})

	r.Run(":8080")
}

type User struct {
	Time time.Time `json:"time" validate:"required" filter:"str2time"`
}

type customValidator struct{}

func (c *customValidator) ValidateStruct(ptr interface{}) error {
	v := validate.Struct(ptr)
	v.Validate() // do validating

	if v.Errors.Empty() {
		return nil
	}

	return v.Errors
}

func (c *customValidator) Engine() interface{} {
	return nil
}

post请求发送json数据

{"time":"2018-10-16 12:34:01"}

输出结果

出错parsing time "\"2018-10-16 12:34:01\"" as "\"2006-01-02T15:04:05Z07:00\"": cannot parse " 12:34:01\"" as "T"

为什么不能解析?

另外在strutil/convert.go代码中

		// has 'T' eg: "2006-01-02T15:04:05"
		if strings.ContainsRune(s, 'T') {
			layout = strings.Replace(layout, " ", "T", -1)
		}

		// eg: "2006/01/02 15:04:05"
		if strings.ContainsRune(s, '/') {
			layout = strings.Replace(layout, "-", "/", -1)
		}

strings.Replace函数的第2个与第3个参数是不是写反了?

Wildcard (*) not working in maputil.GetByPath

System (please complete the following information):

  • OS: linux
  • GO Version: 1.20.5
  • Pkg Version: 0.6.11

Describe the bug

Wildcard (*) not working in maputil.GetByPath

To Reproduce

My Body from API:

{
  "success": true,
  "result": {
    "total": 2,
    "records": [
      {
        "id": "59fab0fa-8f0a-4065-8863-1dae40166015"
      },
      {
        "id": "7c1bd7f9-2ef4-44c8-9756-2e85156ca58f"
      }
    ]
  }
}

This work:

var tcBody := map[string]any{
	"success":                  true,
	"result.records.0.id": "59fab0fa-8f0a-4065-8863-1dae40166015",
	"result.records.1.id": "7c1bd7f9-2ef4-44c8-9756-2e85156ca58f",
}

body, _ := io.ReadAll(response.Body)
var resp map[string]any
json.Unmarshal(body, &resp)
for key, want := range tcBody {
	val, _ := maputil.GetByPath(key, resp)
	if val != want {
		t.Errorf("Body key [%v] was incorrect, got: %v, want: %v", key, val, want)
	}
}

This doesn't work when use wildcard:

var tcBody := map[string]any{
"success":                 true,
"result.records.*.id": []String{
	"59fab0fa-8f0a-4065-8863-0dae40166015",
	"7c1bd7f9-2ef4-44c8-9756-0e85156ca58f",
}

body, _ := io.ReadAll(response.Body)
var resp map[string]any
json.Unmarshal(body, &resp)
for key, want := range tcBody {
	val, _ := maputil.GetByPath(key, resp)
	if val != want {
		t.Errorf("Body key [%v] was incorrect, got: %v, want: %v", key, val, want)
	}
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.