deepcopy

package
v0.9.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 2, 2022 License: MIT, GPL-3.0, MIT Imports: 4 Imported by: 0

README

deepcopy

import "github.com/fufuok/utils/generic/deepcopy"

Package deepcopy implements the proposal https://go.dev/issue/51520.

Example

package main

import (
	"fmt"
	"github.com/fufuok/utils/generic/deepcopy"
	"github.com/fufuok/utils/generic/maps"
	"github.com/fufuok/utils/generic/slices"
	"reflect"
)

func main() {
	type tFN struct {
		fn func() int
	}
	type tMap map[bool][]tFN
	m1 := tMap{true: []tFN{{func() int { return 1 }}}}

	// 深拷贝
	m2 := deepcopy.Value(m1)
	// equal: false 1
	fmt.Printf("equal: %v %+v\n", reflect.DeepEqual(m1, m2), m2[true][0].fn())

	// 浅拷贝
	m3 := maps.Clone[tMap](m1)
	// equal: true 1
	fmt.Printf("equal: %v %+v\n", reflect.DeepEqual(m1, m3), m3[true][0].fn())

	// 改变 m1 后
	m1[true][0] = tFN{func() int { return 0 }}
	// m1: 0, m2: 1, m3: 0
	fmt.Printf("m1: %d, m2: %d, m3: %d\n", m1[true][0].fn(), m2[true][0].fn(), m3[true][0].fn())

	s1 := []tMap{m1}
	s2 := deepcopy.Value(s1)
	s3 := slices.Clone(s1)
	m1[true][0] = tFN{func() int { return 2 }}
	// s1: 2, s2: 0, s3: 2
	fmt.Printf("s1: %d, s2: %d, s3: %d\n", s1[0][true][0].fn(), s2[0][true][0].fn(), s3[0][true][0].fn())

}
Output
equal: false 1
equal: true 1
m1: 0, m2: 1, m3: 0
s1: 2, s2: 0, s3: 2

Index

func Value

func Value[T any](src T) (dst T)

Value copies src to dst recursively.

Two values of identical type are deeply copied if one of the following cases apply.

Numbers, bools, strings are deeply copied and have different underlying memory address.

Slice and Array values are deeply copied, including its elements.

Map values are deeply copied for all of its key and corresponding values.

Pointer values are deeply copied for their pointed value, and the pointer points to the deeply copied value.

Struct values are deeply copied for all fields, including exported and unexported.

Interface values are deeply copied if the underlying type can be deeply copied.

There are a few exceptions that may result in a deeply copied value not deeply equal (asserted by DeepEqual(dst, src)) to the source value:

1) Func values are still refer to the same function 2) Chan values are replaced by newly created channels 3) One-way Chan values (receive or read-only) values are still refer to the same channel

Note that while correct uses of Value do exist, they are not rare. The use of Value often indicates the copying object does not contain a singleton or is never meant to be copied, such as sync.Mutex, os.File, net.Conn, js.Value, etc. In these cases, the copied value retains the memory representations of the source value but may result in unexpected consequences in follow-up usage, the caller should clear these values depending on their usage context.

Example

package main

import (
	"fmt"
	"github.com/fufuok/utils/generic/deepcopy"
)

func main() {
	tests := []any{
		`"Now cut that out!"`,
		39,
		true,
		false,
		2.14,
		[]string{
			"Phil Harris",
			"Rochester van Jones",
			"Mary Livingstone",
			"Dennis Day",
		},
		[2]string{
			"Jell-O",
			"Grape-Nuts",
		},
	}

	for _, expected := range tests {
		actual := deepcopy.Value(expected)
		fmt.Println(actual)
	}
}
Output
"Now cut that out!"
39
true
false
2.14
[Phil Harris Rochester van Jones Mary Livingstone Dennis Day]
[Jell-O Grape-Nuts]

Generated by gomarkdoc

Documentation

Overview

Package deepcopy implements the proposal https://go.dev/issue/51520.

Example
package main

import (
	"fmt"
	"reflect"

	"github.com/fufuok/utils/generic/deepcopy"
	"github.com/fufuok/utils/generic/maps"
	"github.com/fufuok/utils/generic/slices"
)

func main() {
	type tFN struct {
		fn func() int
	}
	type tMap map[bool][]tFN
	m1 := tMap{true: []tFN{{func() int { return 1 }}}}

	// 深拷贝
	m2 := deepcopy.Value(m1)
	// equal: false 1
	fmt.Printf("equal: %v %+v\n", reflect.DeepEqual(m1, m2), m2[true][0].fn())

	// 浅拷贝
	m3 := maps.Clone[tMap](m1)
	// equal: true 1
	fmt.Printf("equal: %v %+v\n", reflect.DeepEqual(m1, m3), m3[true][0].fn())

	// 改变 m1 后
	m1[true][0] = tFN{func() int { return 0 }}
	// m1: 0, m2: 1, m3: 0
	fmt.Printf("m1: %d, m2: %d, m3: %d\n", m1[true][0].fn(), m2[true][0].fn(), m3[true][0].fn())

	s1 := []tMap{m1}
	s2 := deepcopy.Value(s1)
	s3 := slices.Clone(s1)
	m1[true][0] = tFN{func() int { return 2 }}
	// s1: 2, s2: 0, s3: 2
	fmt.Printf("s1: %d, s2: %d, s3: %d\n", s1[0][true][0].fn(), s2[0][true][0].fn(), s3[0][true][0].fn())

}
Output:

equal: false 1
equal: true 1
m1: 0, m2: 1, m3: 0
s1: 2, s2: 0, s3: 2

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Value

func Value[T any](src T) (dst T)

Value copies src to dst recursively.

Two values of identical type are deeply copied if one of the following cases apply.

Numbers, bools, strings are deeply copied and have different underlying memory address.

Slice and Array values are deeply copied, including its elements.

Map values are deeply copied for all of its key and corresponding values.

Pointer values are deeply copied for their pointed value, and the pointer points to the deeply copied value.

Struct values are deeply copied for all fields, including exported and unexported.

Interface values are deeply copied if the underlying type can be deeply copied.

There are a few exceptions that may result in a deeply copied value not deeply equal (asserted by DeepEqual(dst, src)) to the source value:

  1. Func values are still refer to the same function
  2. Chan values are replaced by newly created channels
  3. One-way Chan values (receive or read-only) values are still refer to the same channel

Note that while correct uses of Value do exist, they are not rare. The use of Value often indicates the copying object does not contain a singleton or is never meant to be copied, such as sync.Mutex, os.File, net.Conn, js.Value, etc. In these cases, the copied value retains the memory representations of the source value but may result in unexpected consequences in follow-up usage, the caller should clear these values depending on their usage context.

Example
package main

import (
	"fmt"

	"github.com/fufuok/utils/generic/deepcopy"
)

func main() {
	tests := []any{
		`"Now cut that out!"`,
		39,
		true,
		false,
		2.14,
		[]string{
			"Phil Harris",
			"Rochester van Jones",
			"Mary Livingstone",
			"Dennis Day",
		},
		[2]string{
			"Jell-O",
			"Grape-Nuts",
		},
	}

	for _, expected := range tests {
		actual := deepcopy.Value(expected)
		fmt.Println(actual)
	}
}
Output:

"Now cut that out!"
39
true
false
2.14
[Phil Harris Rochester van Jones Mary Livingstone Dennis Day]
[Jell-O Grape-Nuts]

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL