Is Go language referenced or not? (Compare C++)

  • 2020-06-07 04:40:20
  • OfStack

Three methods of parameter passing in C++

Value delivery:

One of the most common methods of parameter transmission is that the formal parameters of a function are copies of the arguments. Changing the formal parameters in a function does not affect the formal parameters outside the function. Value passing is typically used when a function changes parameters internally without affecting the caller.

Pointer passed

A parameter is a pointer to the address of an argument, and as the name implies, the argument itself is modified by manipulating what the argument points to in a function.

reference

In C++, a reference is an alias for a variable, which is actually the same thing and has the same address in memory. In other words, wherever you operate on a reference, you operate fairly directly on the referenced variable.

See below demo:


#include <iostream>
// Value passed 
void func1(int a) {
  std::cout << " Value passing, variable address: " << &a << ",  A variable's value: " << a << std::endl;
  a ++ ;
}
// Pointer passed 
void func2 (int* a) {
  std::cout << " Pointer passed, variable address: " << a << ",  A variable's value: " << *a << std::endl;
  *a = *a + 1;
}
// reference 
void func3 (int& a) {
  std::cout << " Pointer passed, variable address: " << &a << ",  A variable's value: " << a << std::endl;
  a ++;
}
int main() {
  int a = 5;
  std::cout << " Actual address of variable: " << &a << ",  A variable's value: " << a << std::endl;
  func1(a);
  std::cout << " Value passed after operation , A variable's value: " << a << std::endl;
  std::cout << " Actual address of variable: " << &a << ",  A variable's value: " << a << std::endl;
  func2(&a);
  std::cout << " Pointer passes after operation , A variable's value: " << a << std::endl;
  std::cout << " Actual address of variable: " << &a << ",  A variable's value: " << a << std::endl;
  func3(a);
  std::cout << " After the reference is passed , A variable's value: " << a << std::endl;
  return 0;
}

The output results are as follows:

Actual address of variable: 0x28feac, variable value: 5
Value passed, variable address: 0x28fe90, variable value: 5
After value transfer operation, variable value: 5
Actual address of variable: 0x28feac, variable value: 5
Pointer passed, variable address: 0x28feac, variable value: 5
After the pointer passes the operation, the variable value is: 6
Actual address of variable: 0x28feac, variable value: 6
Pointer passed, variable address: 0x28feac, variable value: 6
After the reference is passed, the variable value is: 7

Parameter passing in Go

As mentioned above, C++ has three methods of parameter passing. Value passing and pointer passing are easy to understand, so does Go also have these methods of parameter passing? This has been debated, but compared to the concept of C++ referential delivery, we can say that Go has no referential delivery. Why? Because Go has no reference to variables. But Go has reference types, which will be explained later.

Let's start with an example of Go passing values and Pointers:


package main
import (
  "fmt"
)
func main() {
  a := 1
  fmt.Println( " Actual address of variable :", &a, " A variable's value :", a)
  func1 (a)
  fmt.Println( " Value passed after operation , A variable's value :", a)
  fmt.Println( " Actual address of variable :", &a, " A variable's value :", a)
  func2(&a)
  fmt.Println( " Pointer passes after operation , A variable's value :", a)
}
// Value passed 
func func1 (a int) {
  a++
  fmt.Println( " Value passed, variable address :", &a, " A variable's value :", a)
}
// Pointer passed 
func func2 (a *int) {
  *a = *a + 1
  fmt.Println( " Pointer passed, variable address :", a, " A variable's value :", *a)
}

The output results are as follows:

Variable physical address: 0 xc04203c1d0 variable values: 1
Value passed, variable address: 0xc04203c210 variable value: 2
After value transfer operation, variable value: 1
Variable physical address: 0 xc04203c1d0 variable values: 1
Passing, variable pointer address: 0 xc04203c1d0 variable values: 2
After the pointer passes the operation, the variable value is: 2
As you can see, the value passing and pointer passing of the basic Go type are no different from C++, but it has no reference to variables. What about the reference types of Go?

Reference type for Go

In Go, reference types include slices, dictionaries, channels, and so on. Take slices for example. Is a slice a reference?

Here's an example:


package main
import (
  "fmt"
)
func main() {
  m1 := make([]string, 1)
  m1[0] = "test"
  fmt.Println(" call  func1  before  m1  value :", m1)
  func1(m1)
  fmt.Println(" call  func1  after  m1  value :", m1)
}
func func1 (a []string) {
  a[0] = "val1"
  fmt.Println("func1 In the :", a)
}

The output results are as follows:

Value of m1 before calling func1: [test]

func1: [val1]

m1 value after calling func1: [val1]

Modifications to slices in the function affect the actual parameter values. Student: Does that mean that the quote passes?

No, to answer that question, you have to figure out whether the call to the function slice m1 has changed at all. First we need to understand the nature of the slices.

A slice is a description of an array fragment. It contains the pointer to the array, the length of the fragment.

In other words, what we are printing above is not the slice itself, but the array that the slice points to. For another example, check to see if 1 slice has changed at all.


  package main
import (
  "fmt"
)
func main() {
  m1 := make([]string, 1)
  m1[0] = "test"
  fmt.Println(" call  func1  before  m1  value :", m1, cap(m1))
  func1(m1)
  fmt.Println(" call  func1  after  m1  value :", m1, cap(m1))
}
func func1 (a []string) {
  a = append(a, "val1")
  fmt.Println("func1 In the :", a, cap(a))
}

The output results are as follows:

The value of m1 before calling func1: [test] 1

In func1: [test val1] 2

The value of m1 after calling func1: [test] 1

This result shows that the slicing did not change before and after the call. The so-called "change" in the previous example is actually a change in the element of the array to which the pointer to the array in the slice refers, which may be a mouthful, but it is. Again, the reference type is not ES137en-ES138en-ES139en.

Want to thoroughly understand that 1 slice is a description of 1 array fragment. It contains a pointer to an array of fragment length of the words, are interested can look at this article: https: / / www ofstack. com/kf / 201604/499045. html. Learn 1 memory model for slicing.

conclusion

The summary is very simple, language also needs to see through the phenomenon to see the essence. Also, the conclusions of this paper should be kept in mind:

There is no pass-by-reference in Go.


Related articles: