Go language deep copy shallow copy
Recently, when writing code, I found a bug, which is related to deep copy and shallow copy
Earlier we looked at the Go language design and implementation – Faith-oriented programming
I’ve talked about it in great detail, and there are two kinds
The arguments are int and array
func myFunction(i int, arr [2]int) {
i = 29
arr[1] = 88
fmt.Printf("in my_funciton - i=(%d, %p) arr=(%v, %p)\n", i, &i, arr, &arr)
}
$ go run main.go
before calling - i=(30.0xc000072008) arr=([66 77].0xc000072010)
in my_funciton - i=(29.0xc000072028) arr=([66 88].0xc000072040)
after calling - i=(30.0xc000072008) arr=([66 77].0xc000072010)
Copy the code
The first is that the arguments in the pass are int and array
You can see that there is no change
So go is value pass-through for both integer and array types
The parameters in the pass are structure and structure pointer
type MyStruct struct {
i int
}
func myFunction(a MyStruct, b *MyStruct) {
a.i = 31
b.i = 41
fmt.Printf("in my_function - a=(%d, %p) b=(%v, %p)\n", a, &a, b, &b)
}
func main(a) {
a := MyStruct{i: 30}
b := &MyStruct{i: 40}
fmt.Printf("before calling - a=(%d, %p) b=(%v, %p)\n", a, &a, b, &b)
myFunction(a, b)
fmt.Printf("after calling - a=(%d, %p) b=(%v, %p)\n", a, &a, b, &b)
}
$ go run main.go
before calling - a=({30}, 0xc000018178) b=(&{40}, 0xc00000c028)
in my_function - a=({31}, 0xc000018198) b=(&{41}, 0xc00000c038)
after calling - a=({30}, 0xc000018178) b=(&{41}, 0xc00000c028)
Copy the code
When a structure and a structure pointer are passed in the argument
You can see that A.I does not change before or after entering the parameter
But B.I changed before and after the entry parameter
And we can see that here
- When passing a structure: all contents of the structure are copied.
- When passing structure pointer: Structure pointer will be copied.
This brings me to my problem
The bug
func (sqli *SqlInjection) GenerateTimePayloads(payloadTemplate string, OriginDict interface{}) [][]fakehttp.Request {
So let’s look at my function calls in the code, one of which is string and one of which is value passing
But how does this interface{} get passed in arguments
So regardless of whether you’re passing in a structure or something else, because it’s not a pointer then you’re going to copy what’s in that structure and pass it around
So I wrote newDict := OriginDict.(url.values)
Interface {} may be passed as a pointer, so let’s test it
I’m going to use interface to pass the structure pointer and the structure and see if there’s any problem
Arrays, ints are definitely passed by value, I think there is no problem
type MyStruct struct {
i int
}
func myFunction(t interface{}, OriginDict interface{}) {
a := t.(MyStruct)
a.i = 31
b := OriginDict.(*MyStruct)
b.i = 41
fmt.Printf("in my_function - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
}
func main(a) {
a := MyStruct{i: 40}
b := &MyStruct{i: 40}
fmt.Printf("before calling - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
myFunction(a, b)
fmt.Printf("after calling - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
}
[Running] go run "/ Users/apple/Desktop/a lot/scanner/Gondar/scanner/test/tesst. Go." "before calling - a=({%! s(int=40)}, 0x140000180f8) b=(&{40}, 0x1400000e028) in my_function - a=({%! s(int=31)}, 0x14000018110) b=(&{41}, 0x1400000e038) after calling - a=({%! s(int=40)}, 0x140000180f8) b=(&{41}, 0x1400000e028)
Copy the code
The result is exactly the same as the previous one, indicating that the structure pointer is passed according to whether or not the structure pointer is passed
Is there something wrong with my thinking
I’m passing a dictionary, so I’m passing a dictionary to try it out
type MyStruct struct {
i int
}
type test map[string] []string
func myFunction(t interface{}, OriginDict interface{}) {
a := t.(test)
a["1"] = []string{"123"}
b := OriginDict.(MyStruct)
b.i = 41
fmt.Printf("in my_function - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
}
func main(a) {
var a test
a = test{
"0": []string{"123"},
}
b := MyStruct{i: 40}
fmt.Printf("before calling - a=(%v, %p) b=(%v, %p)\n", a, &a, b, &b)
myFunction(a, b)
fmt.Printf("after calling - a=(%v, %p) b=(%v, %p)\n", a, &a, b, &b)
}
[Running] go run "/ Users/apple/Desktop/a lot/scanner/Gondar/scanner/test/tesst. Go." "
before calling - a=(map[0: [123]], 0x1400000e028) b=({40}, 0x140000180f8)
in my_function - a=(map[0: [123] 1: [123]], 0x1400000e038) b=({41}, 0x14000018100)
after calling - a=(map[0: [123] 1: [123]], 0x1400000e028) b=({40}, 0x140000180f8)
Copy the code
The problem was rectified, so the pointer was copied when the parameter was passed by interface{}, resulting in the change of the original value
What if instead of an interface, instead of a map is passed directly in parameters
type MyStruct struct {
i int
}
func myFunction(a map[string] []string, OriginDict interface{}) {
a["1"] = []string{"123"}
b := OriginDict.(MyStruct)
b.i = 41
fmt.Printf("in my_function - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
}
func main(a) {
a := map[string] []string{
"0": []string{"123"},
}
b := MyStruct{i: 40}
fmt.Printf("before calling - a=(%v, %p) b=(%v, %p)\n", a, &a, b, &b)
myFunction(a, b)
fmt.Printf("after calling - a=(%v, %p) b=(%v, %p)\n", a, &a, b, &b)
}
[Running] go run "/ Users/apple/Desktop/a lot/scanner/Gondar/scanner/test/tesst. Go." "
before calling - a=(map[0: [123]], 0x1400000e028) b=({40}, 0x140000180f8)
in my_function - a=(map[0: [123] 1: [123]], 0x1400000e038) b=({41}, 0x14000018100)
after calling - a=(map[0: [123] 1: [123]], 0x1400000e028) b=({40}, 0x140000180f8)
Copy the code
The result is the same as the previous one, indicating that the process of passing the interface{} parameter is still the same as its own type
Note The problem is that the map type, which uses pointer passing in the process of passing, is a shallow copy. If the value changes, the original value will change
To summarize
- Pass struct, int, string, array: deep copy;
- Passing structure pointer, map: shallow copy;
Refer to the link
Draveness. Me/golang/docs…