Copier for golang, copy value from struct to struct and more

Copier

I am a copier, I copy everything from one to another

test status

Features

  • Copy from field to field with same name
  • Copy from method to field with same name
  • Copy from field to method with same name
  • Copy from slice to slice
  • Copy from struct to slice
  • Copy from map to map
  • Enforce copying a field with a tag
  • Ignore a field with a tag
  • Deep Copy

Usage

package main

import (
	"fmt"
	"github.com/jinzhu/copier"
)

type User struct {
	Name string
	Role string
	Age  int32

	// Explicitly ignored in the destination struct.
	Salary   int
}

func (user *User) DoubleAge() int32 {
	return 2 * user.Age
}

// Tags in the destination Struct provide instructions to copier.Copy to ignore
// or enforce copying and to panic or return an error if a field was not copied.
type Employee struct {
	// Tell copier.Copy to panic if this field is not copied.
	Name      string `copier:"must"`

	// Tell copier.Copy to return an error if this field is not copied.
	Age       int32  `copier:"must,nopanic"`

	// Tell copier.Copy to explicitly ignore copying this field.
	Salary    int    `copier:"-"`

	DoubleAge int32
	EmployeId int64
	SuperRole string
}

func (employee *Employee) Role(role string) {
	employee.SuperRole = "Super " + role
}

func main() {
	var (
		user      = User{Name: "Jinzhu", Age: 18, Role: "Admin", Salary: 200000}
		users     = []User{{Name: "Jinzhu", Age: 18, Role: "Admin", Salary: 100000}, {Name: "jinzhu 2", Age: 30, Role: "Dev", Salary: 60000}}
		employee  = Employee{Salary: 150000}
		employees = []Employee{}
	)

	copier.Copy(&employee, &user)

	fmt.Printf("%#v \n", employee)
	// Employee{
	//    Name: "Jinzhu",           // Copy from field
	//    Age: 18,                  // Copy from field
	//    Salary:150000,            // Copying explicitly ignored
	//    DoubleAge: 36,            // Copy from method
	//    EmployeeId: 0,            // Ignored
	//    SuperRole: "Super Admin", // Copy to method
	// }

	// Copy struct to slice
	copier.Copy(&employees, &user)

	fmt.Printf("%#v \n", employees)
	// []Employee{
	//   {Name: "Jinzhu", Age: 18, Salary:0, DoubleAge: 36, EmployeId: 0, SuperRole: "Super Admin"}
	// }

	// Copy slice to slice
	employees = []Employee{}
	copier.Copy(&employees, &users)

	fmt.Printf("%#v \n", employees)
	// []Employee{
	//   {Name: "Jinzhu", Age: 18, Salary:0, DoubleAge: 36, EmployeId: 0, SuperRole: "Super Admin"},
	//   {Name: "jinzhu 2", Age: 30, Salary:0, DoubleAge: 60, EmployeId: 0, SuperRole: "Super Dev"},
	// }

 	// Copy map to map
	map1 := map[int]int{3: 6, 4: 8}
	map2 := map[int32]int8{}
	copier.Copy(&map2, map1)

	fmt.Printf("%#v \n", map2)
	// map[int32]int8{3:6, 4:8}
}

Copy with Option

copier.CopyWithOption(&to, &from, copier.Option{IgnoreEmpty: true, DeepCopy: true})

Contributing

You can help to make the project better, check out http://gorm.io/contribute.html for things you can do.

Author

jinzhu

License

Released under the MIT License.

Owner
Comments
  • fix:sql.NullInt32 to int32 and sql.NullByte to byte error

    fix:sql.NullInt32 to int32 and sql.NullByte to byte error

    type A struct {
    	Id sql.NullInt32
    }
    
    type B struct {
    	Id int32
    }
    
    func main() {
    	var a A
    	var b B
    	a = A{Id: sql.NullInt32{Int32: 233, Valid: true}}
    	_ = copier.Copy(&b, a)
    	fmt.Println(a)
    	fmt.Println(b)
    }
    

    the code output is。b.Id not set value

    {{233 true}}
    {0}
    

    Because the value method of sql.NullInt32will convert int32 to Int64。sql.NullInt16 and sql.NullByte are the same

    func (n NullInt32) Value() (driver.Value, error) {
    	if !n.Valid {
    		return nil, nil
    	}
    	return int64(n.Int32), nil
    }
    

    It is false to judge whether the value can be assigned

     if rv.Type().AssignableTo(to.Type()) {
    			to.Set(rv)
    		}
    

    So I added a judgment. If the data is of type int, first convert it to the corresponding type for assignment

    if strings.HasPrefix(rv.Type().String(), "int") && (strings.HasPrefix(to.Type().String(), "int") || strings.HasPrefix(to.Type().String(), "uint")) {
    			convert := rv.Convert(to.Type())
    			to.Set(convert)
    		} else if rv.Type().AssignableTo(to.Type()) {
    			to.Set(rv)
    		}
    
  • [Bug] Copy time.Time not working

    [Bug] Copy time.Time not working

    Reproducible Example

    https://play.golang.org/p/pbA2Z1XJotV

    Description

    Hi everyone,

    I'm not abble to copy structure of type time.Time. See the example above.

    Thanks in advance @jinzhu @math-nao

  • Nested Slice getting copied by reference.

    Nested Slice getting copied by reference.

    Issue demonstrated in following code snippet.

    package main
    
    import (
    	"fmt"
    	"github.com/jinzhu/copier"
    )
    
    type A struct {
    	X []int
    }
    
    type B struct {
    	X []int
    }
    
    func main() {
    	x := []int{1, 50}
    	a := A{X: x}
    	b := B{}
    	copier.Copy(&b, a)
    	fmt.Printf("X0 in B %v %v\n", b.X[0], b.X[1]) // Returns 1
    	fmt.Printf("X0 in A %v %v\n", a.X[0], a.X[1]) // Returns 1
    	a.X[0] = -1
    	a.X[1] = -50
    	fmt.Printf("X in B %v %v\n", b.X[0], b.X[1]) // Returns -1
    	fmt.Printf("X in A %v %v\n", a.X[0], a.X[1]) // Returns -1
    }
    
    
  • Copy with nested pointer to struct causes panic

    Copy with nested pointer to struct causes panic

    The following code causes a panic:

    package main
    
    import "github.com/jinzhu/copier"
    
    func main() {
    	type nested struct {
    		A string
    	}
    	type parentA struct {
    		*nested
    	}
    	type parentB struct {
    		*nested
    	}
    	a := parentA{nested: &nested{A: "a"}}
    	b := parentB{}
    
    	copier.Copy(&b, &a)
    }
    
    

    stack trace:

    $ go run copier_panic.go
    panic: reflect: indirection through nil pointer to embedded struct
    
    goroutine 1 [running]:
    reflect.Value.FieldByIndex(0x4d4fe0, 0xc04206e020, 0x199, 0xc0420500d0, 0x2, 0x2, 0x0, 0x568f40, 0x4c8a00)
            C:/tools/go/src/reflect/value.go:804 +0x276
    reflect.Value.FieldByName(0x4d4fe0, 0xc04206e020, 0x199, 0x4b5ea6, 0x1, 0x4c8a00, 0xc042044250, 0x198)
            C:/tools/go/src/reflect/value.go:820 +0x16e
    github.com/jinzhu/copier.Copy(0x4c2a60, 0xc04206e020, 0x4c2a20, 0xc04206e018, 0x0, 0x0)
            E:/workspace/golang/src/github.com/jinzhu/copier/copier.go:71 +0x491
    main.main()
            E:/workspace/golang/src/playground/copier_panic.go:18 +0xb1
    exit status 2
    

    The issue originates from this: https://github.com/jinzhu/copier/blob/db4671f3a9b8df855e993f7c94ec5ef1ffb0a23b/copier.go#L71

    Is this something that can be fixed in copier? I don't know enough about reflection but if you can guide me, I can make a PR to fix this.

  • [Bug] Panic on SetMapIndex when using map[x]interface{}

    [Bug] Panic on SetMapIndex when using map[x]interface{}

    Reproducible Example

    https://play.golang.org/p/RJOgBhY1oGo

    Description

    Hi everyone,

    I'm facing again a panic using the CopyWithOptions() method. See above the example.

    It seems this is related to map[x]interface{} @jinzhu

  • [Bug] crashed with nested struct

    [Bug] crashed with nested struct

    Reproducible Example

    https://play.golang.org/p/INvrWLUd6BD

    code samples

    package main
    
    import (
    	"github.com/jinzhu/copier"
    )
    
    func main() {
    	type Basic struct {
    		ID   int
    		Name string
    		Addr string
    	}
    
    	type S struct {
    		Basic
    		Level int
    	}
    
    	s1 := S{}
    
    	var s2 S
    	copier.Copy(&s2, s1)
    
    }
    
    

    Description

    Crashed with nested struct. seemed cause by copier.go+193.

    if f, ok := dest.Type().FieldByName(name); ok {
    for idx, x := range f.Index {
    	destFieldKind := dest.Field(x).Kind()
    

    as mentioned by: https://golang.org/pkg/reflect/#StructField

    " Index []int // index sequence for Type.FieldByIndex ", the index can't used by dest.Field(x)

  • Full support sql.Null* structs on both sides. Copy to Scanner interface and from Valuer interface.

    Full support sql.Null* structs on both sides. Copy to Scanner interface and from Valuer interface.

    Right copy of:

    sql.Null* -> generic types

    • sql.NullString -> string
    • sql.NullTime -> time.Time
    • etc...

    sql.Null* -> ptr to generic types

    • sql.NullString -> *string
    • etc...

    Or vice versa:

    generic types -> sql.Null*

    • string -> sql.NullString
    • time.Time -> sql.NullTime
    • etc...

    ptr to generic types -> sql.Null*

    • *string -> sql.NullString
    • *time.Time -> sql.NullTime
    • etc...

    Totally covered by tests.

  • Copy map with slice-type value panic

    Copy map with slice-type value panic

    Reproducible Example

    fromMap := make(map[string][]int32)
    slice := []int32{1, 2}
    fromMap["key1"] = slice
    toMap := make(map[string][]int32)
    copier.Copy(&toMap, fromMap)
    

    Description

    copy a map which has slice-type value will report error: reflect.Value.Addr of unaddressable value

  • Copy un-exported struct fields in DeepCopy

    Copy un-exported struct fields in DeepCopy

    This should fix issues #97 and #98. Like PR #105, it is not specific to time.Time, but resolves the issue by ensuring un-exported fields of a struct are copied, even when DeepCopy: true.

    The idea was inspired by PR #105, but the structure is quite different. PR #105 did not resolve the issue I faced or make tests pass. This PR does both.

    I retained the tests added by PRs #103 and #105 and added a few more cases that exhibit the specific issue I faced.

  • <feat>: add CopyByTag  extend

    : add CopyByTag extend

    copy field by specifying a tag. This will make field type conversion very easy. Allows to copy fields of different types even with different names.

    example

    type structSameName1Tag struct {
    	Aa string    `mson:"A_string"`
    	B int64     `mson:"B_int64"`
    	C time.Time `mson:"C_time_Time"`
    }
    
    type structSameName2Tag struct {
    	A string    `mson:"A_string"`
    	B time.Time `mson:"B_time_Time"`
    	C int64     `mson:"C_int64"`
    }
    
    func (s *structSameName2Tag) C_time_Time(t time.Time){
    	s.C = t.Unix()
    }
    func (s *structSameName2Tag) B_int64(B int64){
    	s.B = time.Unix(B,0)
    }
    func TestCopyFieldsWithSameNameButDifferentTypesTag(t *testing.T) {
    	obj1 := structSameName1Tag{Aa: "123", B: 2, C: time.Now()}
    	obj2 := &structSameName2Tag{}
    	err := copier.CopyByTag(obj2, &obj1,"mson")
    	if err != nil {
    		t.Error("Should not raise error")
    	}
    
    	if obj2.A != obj1.Aa {
    		t.Errorf("Field A should be copied")
    	}
    	if obj2.B.Unix() != obj1.B{
    		t.Errorf("Field B should be copied")
    	}
    	if obj2.C != obj1.C.Unix(){
    		t.Errorf("Field C should be copied")
    	}
    }
    
  • fix copy same struct with pointer fields

    fix copy same struct with pointer fields

    fix a bug, when we're copying the same struct which has pointer fields, we'll get the same address of pointer field on original and new one after copy. After this fix, it will be ok!

  • 在两个含有 map[string]int 的结构体复制后,新对象改动,会影响原`src`内的map

    在两个含有 map[string]int 的结构体复制后,新对象改动,会影响原`src`内的map

    Reproducible Example

    有两个变量都是同一种结构体类型,结构体内有 map,slice,和子结构体。在调用 copier.Copy 复制后,改变 dst 对象内的 map,居然对原 scr 里面的 map 产生了影响,我的预期是复制后,就是彼此独立的对象和map了。

    Description

    测试代码:

    package main
    
    import (
        "fmt"
        "github.com/davecgh/go-spew/spew"
        "github.com/jinzhu/copier"
    )
    
    type SC struct {
        C uint8
    }
    
    type Map1 struct {
        M map[string]int32
        C *SC
    }
    
    func TestCopier() {
        var src = Map1{map[string]int32{"C:": 3, "d": 4}, []int32{9, 8}, &SC{32}}
        var dst1 = Map1{}
        copier.Copy(&dst1, src)
        spew.Printf("1. before src %+v\t\tdst1 %+v\n", src, dst1)
        fmt.Printf("1. before src.map %p\tdst1 %p\n", &src.M, &dst1.M)
        dst1.M["F"] = 5
        dst1.M["g"] = 6
        dst1.A[0] = 7
        dst1.C.C = 27
        spew.Printf("1. after  src %+v\tdst1 %+v\n", src, dst1)
        fmt.Printf("1. after  src.map %p\tdst1 %p\n\n", &src.M, &dst1.M)
    
        var dst2 = Map1{}
        copier.Copy(&dst2, src)
        spew.Printf("2. before src %+v\t\tdst1 %+v\t\t\tdst2 %+v\n", src, dst1, dst2)
        fmt.Printf("2. before src.map %p\tdst1 %p\tdst2 %p\n", &src.M, &dst1.M, &dst2.M)
        dst2.M["H"] = 7
        dst2.M["i"] = 8
        dst1.A[0] = 6
        dst1.C.C = 62
        spew.Printf("2. after  src %+v\tdst1 %+v\t\tdst2 %+v\n", src, dst1, dst2)
        fmt.Printf("2. after  src.map %p\t dst1.map %p\t dst2.map %p\n\n", &src.M, &dst1.M, &dst2.M)
    
        var dst3 = Map1{}
        src.M = map[string]int32{"C:": 3, "d": 4}
        copier.Copy(&dst3, src)
        spew.Printf("3. before src %+v\t\tdst1 %+v\t\t\tdst3 %+v\n", src, dst1, dst3)
        fmt.Printf("3. before src.map %p\tdst1 %p\tdst2 %p\tdst3.map %p\n", &src.M, &dst1.M, &dst1.M, &dst3.M)
        dst3.M["H"] = 7
        dst3.M["i"] = 8
        dst1.A[0] = 5
        dst1.C.C = 57
        spew.Printf("3. after  src %+v\tdst1 %+v\t\tdst3 %+v\n", src, dst1, dst3)
        fmt.Printf("3. after  src.map %p\t dst1.map %p\t dst2.map %p\tdst3.map %p\n\n",
            &src.M, &dst1.M, &dst2.M, &dst3.M)
    }
    

    运行输出:

    1. before src {M:map[C::3 d:4] A:[9 8] C:<*>(0xc000018278){C:32}}		dst1 {M:map[C::3 d:4] A:[9 8] C:<*>(0xc000018308){C:32}}
    1. before src.map 0xc0000643c0	dst1 0xc000064420
    1. after  src {M:map[g:6 C::3 d:4 F:5] A:[7 8] C:<*>(0xc000018278){C:32}}	dst1 {M:map[F:5 g:6 C::3 d:4] A:[7 8] C:<*>(0xc000018308){C:27}}
    1. after  src.map 0xc0000643c0	dst1 0xc000064420
    
    2. before src {M:map[g:6 C::3 d:4 F:5] A:[7 8] C:<*>(0xc000018278){C:32}}		dst1 {M:map[C::3 d:4 F:5 g:6] A:[7 8] C:<*>(0xc000018308){C:27}}			dst2 {M:map[C::3 d:4 F:5 g:6] A:[7 8] C:<*>(0xc0000186a0){C:32}}
    2. after  src {M:map[C::3 d:4 F:5 g:6 H:7 i:8] A:[6 8] C:<*>(0xc000018278){C:32}}	dst1 {M:map[C::3 d:4 F:5 g:6 H:7 i:8] A:[6 8] C:<*>(0xc000018308){C:62}}		dst2 {M:map[C::3 d:4 F:5 g:6 H:7 i:8] A:[6 8] C:<*>(0xc0000186a0){C:32}}
    2. after  src.map 0xc0000643c0	 dst1.map 0xc000064420	 dst2.map 0xc000064780
    
    3. before src {M:map[C::3 d:4] A:[6 8] C:<*>(0xc000018278){C:32}}		dst1 {M:map[g:6 H:7 i:8 C::3 d:4 F:5] A:[6 8] C:<*>(0xc000018308){C:62}}			dst3 {M:map[C::3 d:4] A:[6 8] C:<*>(0xc000018cc8){C:32}}
    3. after  src {M:map[C::3 d:4 H:7 i:8] A:[5 8] C:<*>(0xc000018278){C:32}}	dst1 {M:map[H:7 i:8 C::3 d:4 F:5 g:6] A:[5 8] C:<*>(0xc000018308){C:57}}		dst3 {M:map[C::3 d:4 H:7 i:8] A:[5 8] C:<*>(0xc000018cc8){C:32}}
    3. after  src.map 0xc0000643c0	 dst1.map 0xc000064420	 dst2.map 0xc000064780	dst3.map 0xc000064ba0
    
    2022/11/12 18:35:51 go-learn end at 2022-11-12 18:35:51.550851 +0800 CST m=+0.000847494 duration is 0 ms
    Pauls-MBP:go-learn paulxu$ go run ./cmd/main.go
    2022/11/12 18:37:21 go-learn start at 2022-11-12 18:37:21.187705 +0800 CST m=+0.000306917
    1. before src {M:map[C::3 d:4] A:[9 8] C:<*>(0xc0000b61e8){C:32}}		dst1 {M:map[C::3 d:4] A:[9 8] C:<*>(0xc0000b6278){C:32}}
    1. before src.map 0xc0000983c0	dst1 0xc000098420
    1. after  src {M:map[C::3 d:4 F:5 g:6] A:[7 8] C:<*>(0xc0000b61e8){C:32}}	dst1 {M:map[d:4 F:5 g:6 C::3] A:[7 8] C:<*>(0xc0000b6278){C:27}}
    1. after  src.map 0xc0000983c0	dst1 0xc000098420
    
    2. before src {M:map[C::3 d:4 F:5 g:6] A:[7 8] C:<*>(0xc0000b61e8){C:32}}		dst1 {M:map[C::3 d:4 F:5 g:6] A:[7 8] C:<*>(0xc0000b6278){C:27}}			dst2 {M:map[d:4 F:5 g:6 C::3] A:[7 8] C:<*>(0xc0000b6610){C:32}}
    2. before src.map 0xc0000983c0	dst1 0xc000098420	dst2 0xc000098780
    2. after  src {M:map[H:7 i:8 C::3 d:4 F:5 g:6] A:[6 8] C:<*>(0xc0000b61e8){C:32}}	dst1 {M:map[g:6 H:7 i:8 C::3 d:4 F:5] A:[6 8] C:<*>(0xc0000b6278){C:62}}		dst2 {M:map[H:7 i:8 C::3 d:4 F:5 g:6] A:[6 8] C:<*>(0xc0000b6610){C:32}}
    2. after  src.map 0xc0000983c0	 dst1.map 0xc000098420	 dst2.map 0xc000098780
    
    3. before src {M:map[C::3 d:4] A:[6 8] C:<*>(0xc0000b61e8){C:32}}		dst1 {M:map[C::3 d:4 F:5 g:6 H:7 i:8] A:[6 8] C:<*>(0xc0000b6278){C:62}}			dst3 {M:map[C::3 d:4] A:[6 8] C:<*>(0xc0000b6c38){C:32}}
    3. before src.map 0xc0000983c0	dst1 0xc000098420	dst2 0xc000098420	dst3.map 0xc000098ba0
    3. after  src {M:map[d:4 H:7 i:8 C::3] A:[5 8] C:<*>(0xc0000b61e8){C:32}}	dst1 {M:map[i:8 C::3 d:4 F:5 g:6 H:7] A:[5 8] C:<*>(0xc0000b6278){C:57}}		dst3 {M:map[i:8 C::3 d:4 H:7] A:[5 8] C:<*>(0xc0000b6c38){C:32}}
    3. after  src.map 0xc0000983c0	 dst1.map 0xc000098420	 dst2.map 0xc000098780	dst3.map 0xc000098ba0
    

    从以上输出 结果看到 src 内的 map 在调用 copier.Copy 方法后,编辑新的dst对象的 map,和子结构体后,src的字结构体不影响,但map也产生了改变。

    我的预期是:在 copy出一个新对象后,对新对象的任何编辑,都不应该影响原对象。

    所以:

    1. 这是个bug
    2. 提问者才疏学浅,这是预期的表现
    3. 使用copier的方式不对
    4. golang限制,做不到提问者的预期
  • 特定场景无法匹配到TypeConverter

    特定场景无法匹配到TypeConverter

    copier 在特定场景无法匹配到TypeConverter, 如下面四种场景, 实际上仅有一个能匹配到.

    type A struct {
    	A int
    }
    
    type B struct {
    	A int
    	b int
    }
    
    func Test_A(t *testing.T) {
    
    	opt := copier.Option{
    		Converters: []copier.TypeConverter{
    			{
    				SrcType: A{},
    				DstType: B{},
    				Fn: func(from interface{}) (interface{}, error) {
    					fmt.Print("match TypeConverter ")
    					return nil, nil
    				},
    			},
    		},
    	}
    
    	{
    		aa := A{A: 10}
    		bb := B{A: 10, b: 100}
    		t.Logf("err: %v", copier.CopyWithOption(&bb, &aa, opt))
    	}
    
    	{
    		aa := map[string]*A{
    			"a": &A{A: 10},
    		}
    
    		bb := map[string]*B{
    			"a": &B{A: 10, b: 100},
    		}
    
    		t.Logf("err: %v", copier.CopyWithOption(&bb, &aa, opt))
    	}
    	{
    		aa := []*A{
    			&A{A: 10},
    		}
    
    		bb := []*B{
    			&B{A: 10, b: 100},
    		}
    
    		t.Logf("err: %v", copier.CopyWithOption(&bb, &aa, opt))
    
    		// b := B{A: 10, b: 100}
    		// dst2 := []*B{&b}
    		// t.Logf("copy a->*b err: %v, b: %+v", copier.CopyWithOption(&dst2, []*A{&a}, opt), b)
    	}
    
    	{
    		aa := struct {
    			A []*A
    		}{
    			A: []*A{&A{A: 10}},
    		}
    
    		bb := struct {
    			A []*B
    		}{
    			A: []*B{&B{A: 10, b: 100}},
    		}
    
    		t.Logf("err: %v", copier.CopyWithOption(&bb, &aa, opt))
    
    		// b := B{A: 10, b: 100}
    		// dst2 := []*B{&b}
    		// t.Logf("copy a->*b err: %v, b: %+v", copier.CopyWithOption(&dst2, []*A{&a}, opt), b)
    	}
    
    }
    
  • nopanic Tag无效

    nopanic Tag无效

    Reproducible Example

    copier:"must,nopanic"无法返回错误

    Description

    copier:"must,nopanic" 在未发生拷贝时无法返回错误 copier:"must, nopanic" 在未发生拷贝时可以返回错误 区别逗号后多了一个空格 go version 1.16

  • Added DefaultSourceFlags option

    Added DefaultSourceFlags option

    Hey Jinzhu! Nice work on the library! I was looking for a way to copy all fields from one nested structure to another while also warning me if any fields are missing in the destination structure. Adding copier tags across many fields would add too much noise. So, I've decided to add a "default flag" option to copier itself. Thought you might find it useful too.

read copy update map for golang 1.18+

(R)ead-(C)opy-Update read copy update map for golang 1.18+ How it works This is a simple generic implementation for https://en.wikipedia.org/wiki/Read

Dec 11, 2022
Steampipe plugin to query your Scalingo apps, addons and more

Scalingo plugin for Steampipe Use SQL to query infrastructure including applications and addons from Scalingo. Get started → Documentation: Table defi

Nov 4, 2022
💪 Helper Utils For The Go: string, array/slice, map, format, cli, env, filesystem, test and more.
💪 Helper Utils For The Go: string, array/slice, map, format, cli, env, filesystem, test and more.

?? Helper Utils For The Go: string, array/slice, map, format, cli, env, filesystem, test and more. Go 的一些工具函数,格式化,特殊处理,常用信息获取等等

Jan 6, 2023
Tugas Alta Immersive Backend Golang Fundamental Programming (Pointer, Struct, Method, Interface)
Tugas Alta Immersive Backend Golang Fundamental Programming (Pointer, Struct, Method, Interface)

Tatacara Melakukan Setup Tugas clone project ini dengan cara git clone https://github.com/Immersive-Backend-Resource/Pointer-Struct-Method-Interface.g

Jan 9, 2022
F - Experimenting with Go 1.18 generics to write more functional Go code

f f is a simple library that leverages the new generics in Golang to create a tools for functional style of code. Pipe like '|>' in Elixir or Elm. inp

Apr 12, 2022
Leftright - A concurrent map that is optimized for scenarios where reads are more frequent than writes

leftright A concurrent map that is optimized for scenarios where reads are more

Jan 30, 2022
Utility package that provides the ability to more conveniently work with URL parameters.

Utility package that provides the ability to more conveniently work with URL parameters.

Feb 8, 2022
Robust & Easy to use struct mapper and utility methods for Go

go-model Robust & Easy to use model mapper and utility methods for Go struct. Typical methods increase productivity and make Go development more fun ?

Dec 30, 2022
reflect api without runtime reflect.Value cost

reflect2 reflect api that avoids runtime reflect.Value cost reflect get/set interface{}, with type checking reflect get/set unsafe.Pointer, without ty

Jan 4, 2023
Helm plugin to reference value files packaged in dependency charts

Helm Octopus Plugin This Helm plugin allows to reference packaged value files (other than the default values.yaml). Install helm plugin install https:

Sep 23, 2021
A Runtime Struct Builder for Go

A Runtime Struct Builder for Go

Jul 8, 2022
Go tool to modify struct field tags
Go tool to modify struct field tags

Go tool to modify/update field tags in structs. gomodifytags makes it easy to update, add or delete the tags in a struct field. You can easily add new tags, update existing tags (such as appending a new key, i.e: db, xml, etc..) or remove existing tags

Jan 1, 2023
Go linter to check the struct literal to use field name

Structfield Find struct literals using non-labeled fields. The structfield analysis reports the usage of struct literal using non-labeled fields more

Aug 23, 2021
gin struct controller

gin struct controller

Oct 4, 2021
Highly configurable struct to map converter.

Mapify Highly configurable struct to map converter. Will convert maps into other maps as well (work in progress). Features configuration outside the s

Jul 30, 2022
Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/rpc package.
Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/rpc package.

Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/rpc package. The library allows you to call Go service methods from PHP with a minimal footprint, structures and []byte support.

Dec 28, 2022
A Go (golang) library for parsing and verifying versions and version constraints.

go-version is a library for parsing versions and version constraints, and verifying versions against a set of constraints. go-version can sort a collection of versions properly, handles prerelease/beta versions, can increment versions, etc.

Jan 9, 2023
Golang: unify nil and empty slices and maps

unifynil, unify nil and empty slices and maps in Golang Empty slices and maps can be nil or not nil in Go. It may become a nightmare in tests and JSON

Jan 16, 2022
memresolver is an in-memory golang resolver that allows to override current golang Lookup func literals

mem-resolver memresolver is an in-memory golang resolver that allows to override current golang Lookup func literals How to use it Create your custom

Jun 23, 2022