Skip to content

Commit

Permalink
Merge pull request #3 from tiendc/add-guidelines
Browse files Browse the repository at this point in the history
Add guidelines
  • Loading branch information
tiendc committed Jul 11, 2023
2 parents 1147b47 + d316eb8 commit d200209
Showing 1 changed file with 231 additions and 5 deletions.
236 changes: 231 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,233 @@ go get github.com/tiendc/go-deepcopy

## Usage

TBD
- [First example](#first-example)
- [Copy between struct fields with different names](#copy-between-struct-fields-with-different-names)
- [Ignore copying struct fields](#ignore-copying-struct-fields)
- [Copy between struct fields and methods](#copy-between-struct-fields-and-methods)
- [Copy between unexported struct fields](#copy-between-unexported-struct-fields)
- [Configure copying behavior](#configure-copying-behavior)

### First example

[Playground](https://go.dev/play/p/GsgjDl1vxVd)

```go
type SS struct {
B bool
}
type S struct {
I int
U uint
St string
V SS
}
type DD struct {
B bool
}
type D struct {
I int
U uint
X string
V DD
}
src := []S{{I: 1, U: 2, St: "3", V: SS{B: true}}, {I: 11, U: 22, St: "33", V: SS{B: false}}}
var dst []D
err := deepcopy.Copy(&dst, src)

for _, d := range dst {
fmt.Printf("%+v\n", d)
}

// Output:
// {I:1 U:2 X: V:{B:true}}
// {I:11 U:22 X: V:{B:false}}
```

### Copy between struct fields with different names

[Playground](https://go.dev/play/p/MY8ReuT2K3Y)

```go
type S struct {
X int `copy:"Key"` // 'Key' is used to match the fields
U uint
St string
}
type D struct {
Y int `copy:"Key"`
U uint
}
src := []S{{X: 1, U: 2, St: "3"}, {X: 11, U: 22, St: "33"}}
var dst []D
err := deepcopy.Copy(&dst, src)

for _, d := range dst {
fmt.Printf("%+v\n", d)
}

// Output:
// {Y:1 U:2}
// {Y:11 U:22}
```

### Ignore copying struct fields

- By default, matching fields will be copied between. If you don't want to copy them, use tag `required`.

[Playground](https://go.dev/play/p/RtlmWN1AEsy)

```go
// S and D both have `I` field, but we don't want to copy
// Tag `-` can be used in both struct definitions or just in one
type S struct {
I int
U uint
St string
}
type D struct {
I int `copy:"-"`
U uint
}
src := []S{{I: 1, U: 2, St: "3"}, {I: 11, U: 22, St: "33"}}
var dst []D
err := deepcopy.Copy(&dst, src)
if err != nil {
fmt.Println("error:", err)
}

for _, d := range dst {
fmt.Printf("%+v\n", d)
}

// Output:
// {I:0 U:2}
// {I:0 U:22}
```

### Copy between struct fields and methods

[Playground 1](https://go.dev/play/p/zb2NU32G2mG)
[Playground 2](https://go.dev/play/p/C3FpFwzoPFm)

```go
type S struct {
X int
U uint
St string
}

type D struct {
x string
U uint
}

// Copy method should be in form of "Copy" + source field name (or key) and return `error` type
func (d *D) CopyX(i int) error {
d.x = fmt.Sprintf("%d", i)
return nil
}
```
```go
src := []S{{X: 1, U: 2, St: "3"}, {X: 11, U: 22, St: "33"}}
var dst []D
err := deepcopy.Copy(&dst, src)

for _, d := range dst {
fmt.Printf("%+v\n", d)
}

// Output:
// {x:1 U:2}
// {x:11 U:22}
```

### Copy between unexported struct fields

- By default, unexported struct fields will be ignored when copy. If you want to copy them, use tag `required`.

[Playground](https://go.dev/play/p/9fNq7kwM1y8)

```go
type S struct {
i int
U uint
St string
}
type D struct {
i int `copy:",required"`
U uint
}
src := []S{{i: 1, U: 2, St: "3"}, {i: 11, U: 22, St: "33"}}
var dst []D
err := deepcopy.Copy(&dst, src)
if err != nil {
fmt.Println("error:", err)
}

for _, d := range dst {
fmt.Printf("%+v\n", d)
}

// Output:
// {i:1 U:2}
// {i:11 U:22}
```

### Configure copying behavior

- Not allow to copy between **ptr** type and **value** (default is allow)

[Playground](https://go.dev/play/p/_SGEYYE4N_m)

```go
type S struct {
I int
U uint
}
type D struct {
I *int
U uint
}
src := []S{{I: 1, U: 2}, {I: 11, U: 22}}
var dst []D
err := deepcopy.Copy(&dst, src, deepcopy.CopyBetweenPtrAndValue(false))
fmt.Println("error:", err)

// Output:
// error: ErrTypeNonCopyable: int -> *int
```

- Ignore error ErrTypeNonCopyable, the copy will not return that error, but the copy won't be performed.

[Playground 1](https://go.dev/play/p/u63SwMKNxU5)
[Playground 2](https://go.dev/play/p/ZomOQW2PsPP)

```go
type S struct {
I []int
U uint
}
type D struct {
I int
U uint
}
src := []S{{I: []int{1, 2, 3}, U: 2}, {I: []int{1, 2, 3}, U: 22}}
var dst []D
// The copy will succeed with ignoring copy of field `I`
err := deepcopy.Copy(&dst, src, deepcopy.IgnoreNonCopyableTypes(true))
if err != nil {
fmt.Println("error:", err)
}

for _, d := range dst {
fmt.Printf("%+v\n", d)
}

// Output:
// {I:0 U:2}
// {I:0 U:22}
```

## Benchmarks

Expand All @@ -30,16 +256,16 @@ TBD

```
BenchmarkCopy/Go-DeepCopy
BenchmarkCopy/Go-DeepCopy-10 664150 1796 ns/op
BenchmarkCopy/Go-DeepCopy-10 664150 1796 ns/op
BenchmarkCopy/ManualCopy
BenchmarkCopy/ManualCopy-10 3047484 391.4 ns/op
BenchmarkCopy/ManualCopy-10 3047484 391.4 ns/op
BenchmarkCopy/JinzhuCopier
BenchmarkCopy/JinzhuCopier-10 64623 18541 ns/op
BenchmarkCopy/JinzhuCopier-10 64623 18541 ns/op
BenchmarkCopy/Deepcopier
BenchmarkCopy/Deepcopier-10 38239 31253 ns/op
BenchmarkCopy/Deepcopier-10 38239 31253 ns/op
```

## Contributing
Expand Down

0 comments on commit d200209

Please sign in to comment.