introduction
As the beginning, there has never been a so-called "reference transfer" in Go lang. There has always been only one variable transfer method, that is, value transfer. Because the premise of reference passing is that there are "reference variables", but there has never been so-called "reference variables" in Go lang, so it is impossible to have such a way of variable passing through reference passing.
Reference Type
First of all, the basic data types of Go lang are value types, such as integers, floating points, strings, booleans, arrays and error types. They are essentially primitive types, that is, they cannot be changed. Therefore, when operating on them, they usually return a newly created value. Therefore, when passing these values to a function, they are actually passing a copy of a value. This is basically no dispute.
The reference type refers to its modification action that can affect any variable that references it. In Go language, reference types include slices, dictionaries, maps, interfaces, functions (funcs), and channels (chan).
The problem is, if we modify the reference type data defined externally within a certain function body:
package main import "fmt" func changeMap(data map[string]string) { data["123"] = "333" } func main() { a := map[string]string{} a["123"] = "123" ("begin:", a) changeMap(a) ("after:", a) }
The program returns:
begin: map[123:123]
after: map[123:333]
Obviously, the function changeMap changes the value of the external dictionary type, so we can conclude that the arguments of the reference type are used to pass the reference?
Reference variable and pass-by-reference
In fact, reference variables and pass-by-reference do exist, but they exist in other languages, such as Python:
a = [2] print(id(a)) def change(a): print(id(a)) (1) if __name__ == '__main__': print(a) change(a) print(a)
Here we define a variable data type: list a, and then pass it into the function change for modification operations. At the same time, we use the built-in id() method of the system to print the modified value and memory address, as well as the modified value and memory address respectively. The program returns:
4311179392
[2]
4311179392
[2, 1]
What does this mean? It shows that variable a is a reference variable, and its passing as a parameter is a reference pass (pass-by-reference). The evidence is that its original memory address is consistent with the memory address passed into the function, both 4311179392.
Therefore, reference variables and reference transfer should have the following characteristics: the memory address of the reference variable is the same as the original variable. Just like in the above example, the memory address of the reference variable a and the original variable a in the function are the same. Functions are passed using references and can change the value of external arguments. Just like in the example above, the change function uses reference pass, changing the value of the external real parameter a.
Does Golang have a reference variable?
There is no reference variable in Golang:
package main import "fmt" func main() { a := 1 var a1 *int = &a var a2 *int = &a ("value", a1, "Memory address:", &a1) ("value:", a2, "Memory address:", &a2) }
The program returns:
Value 0x140000140b8 Memory address: 0x1400000e028
Value: 0x140000140b8 Memory address: 0x1400000e030
Unlike Python, in Go lang, it is impossible for two variables to have the same memory address, so there is no reference variable. The values of variables a1 and a2 are the same, both point to the memory address of variable a, but the memory addresses of variables a1 and a2 are different, while the memory addresses of reference variables in Python are the same as those of the original variable.
Therefore, there are no reference variables in Go language, so there is naturally no reference transmission.
Why can a dictionary pass value but change the original object?
Because although the name of a dictionary is a dictionary or a map, it doesn't matter. In fact, it is a pointer:
package main import ( "fmt" "unsafe" ) func main() { data := make(map[string]int) var p uintptr ("Dictionary size:", (data)) ("Pointer Size:", (p)) }
The program returns:
Dictionary size: 8
Pointer size: 8
From the size of the memory space occupied, we can see that dictionaries and pointers are actually one thing. If the dictionary is a pointer, shouldn't make return *map[string]int? Why do we use dictionary to pass real arguments and never add *?
In the early days of Go lang, it was indeed that the dictionary was used in the form of pointers, but in the end, Golang's designers found that almost no one used the dictionary without pointers, so they directly removed the formal pointer symbol*. In analogy, we will find that in reality, almost no one has called AC Milan AC Milan, and they call it Milan directly, because everyone thinks that Milan is AC Milan, so the formal "AC" is automatically omitted.
In essence, we can understand that the dictionary is passed as a parameter, which is value, but the reference type passes a pointer to the underlying data. Therefore, when we operate, we can modify the value of the shared underlying data, which in turn affects all variables that reference the shared underlying data. This is why the dictionary can affect the original object when operating within the function.
Conclusion
The reason why reference types can be referenced is because we create a variable of reference type, which is actually a header value. The header value contains a pointer pointing to the underlying data structure. When we pass the reference type in the function, we actually pass a copy of this header value. The underlying structure it points to is not copied and passed. This is also the reason why reference type passes efficiently. In other words, Go lang introduced the concept of pointer in order to ensure the purity of value pass. If there are reference variables and reference passes in Go lang, then will not the pointer become a superfluous and slutty brush?
The above is the detailed content of analyzing whether the reference type in Golang is passed in reference. For more information about the reference type of Go, please pay attention to my other related articles!