Follow the old cat to do GO basic advanced

Keywords: Go

Looking back on my last blog, I mainly shared with you the basic syntax of GO language, including variable definition, basic types, conditional statements and circular statements. Then this article starts to synchronize with you the advanced level of GO language foundation.

Definition of function

In fact, some functions have been written in many DEMO last time, but the function definition is not clear. Next, let's also give an example and look directly at the code.

func calculate(a,b int, op string) int {
    switch op {
    case "+":
        return a + b
    case "-":
        return a - b
    case "*":
        return a * b
    case "/":
        return a / b
    default:
        panic("unsupported op")
    }
}

The above is a relatively simple function for calculating the addition, subtraction, multiplication and division of two integers. First, we can see that the definition of the function actually follows the definition of variables. We first define the name of the function, and then the return value of the function. Of course, the same is true for parameter definitions in functions.

In addition, in fact, compared with other languages, GO language has a relatively coquettish operation, that is, it can have multiple return values. For example, let's write an example of division, which we learned in primary school that there is a remainder when division is endless. Let's look at a function.

func div(a int, b int) (int,int){
    return a / b, a % b
}

What do you think of the above return value? In fact, the two final return values do not reflect any business significance. We can't distinguish what the final return result is for. Of course, the GO language also finds this drawback. Therefore, the name of our return value can also be defined, as follows. The quotient obtained by our naming division is q and the remainder is r. after improvement, we get the following:

func div(a int, b int) (q ,r int){
    return a / b, a % b
}

If so, we can get the result by calling main

func main() {
    fmt.Println(div(4,3))
    q,r := div(5,6)
    fmt.Println(q,r)
}

At this time, the problem comes again. If we only want one quotient and don't want the remainder, how to write it, because we all know that in the syntax of go, the variables defined must be used later. Otherwise, a compilation error will be reported. In fact, we can directly replace it with "". The specific code blocks are as follows

func main() {
    q,_ := div(5,6)
    fmt.Println(q)
}

In this way, we can only get one of the values.

In fact, as the functional programming language of GO language, function is very important. Therefore, we can transfer the function itself as a parameter to the function in a more high-end way. It's a little difficult to understand when we begin to accept it. Old cat, write an example here and try to understand it, Of course, later, the old cat will introduce functional programming in more detail. Specific examples are as follows

func apply(op func(int,int) int,a,b int) int{
    fmt.Printf("Calling %s with %d,%d\n",
        runtime.FuncForPC(reflect.ValueOf(op).Pointer()).Name(),a,b)
    return op(a,b)
}

Let's make a simple summary of the functions of GO language:

  • The return value type is written later
  • Multiple values can be returned
  • Functions can be used as arguments
  • There are no default parameters, variable parameters, overloads, etc

Pointer

Related definitions

Most of those who pay attention to the old cat should be students majoring in software. I don't know if you are familiar with the C language. In fact, there are pointers in the C language. The pointers in the C language are relatively difficult. In fact, GO language also has pointers, which is relatively simple, because the pointers of GO language cannot be operated.

A pointer simply means that a pointer points to the memory address of a value.

The de address character in GO language is &. If it is placed before the variable, the corresponding variable memory address will be returned. An ex amp le is as follows:

package main

import "fmt"
func main() {
   var a int = 10  
   fmt.Printf("Address of variable: %x\n", &a  )
}

This is actually the address acquisition method of GO language. How do we access it? Then our pointer will appear, as shown in the following code example

var var_name *var-type

Var type is pointer type, var_name is the name of the pointer variable, * is used to specify that the variable is used as a pointer. Let's look at the following example:

var ip *int        /* Pointing integer*/
var fp *float32    /* Point to floating point */

So the above actually defines two pointers, pointing to int and float32 respectively.

Use pointer

package main

import "fmt"

func main() {
   var a int= 20   /* Declare actual variables */
   var ip *int        /* Declare pointer variables */

   ip = &a  /* Storage address of pointer variable */

   fmt.Printf("a The address of the variable is: %x\n", &a  )

   /* Storage address of pointer variable */
   fmt.Printf("ip Pointer address of variable storage: %x\n", ip )

   /* Accessing values using pointers */
   fmt.Printf("*ip Value of variable: %d\n", *ip )
}

So the result we get is

a The address of the variable is: 20818a220
ip Pointer address of variable storage: 20818a220
*ip Value of variable: 20

In fact, GO language also has null pointers. When a pointer is defined and not assigned to any variables, its value is nil. Nil pointers are also called null pointers. Like null, None, nil and null in other languages, nil conceptually refers to zero value or null value. A pointer variable is usually abbreviated as ptr.

The following example

package main

import "fmt"

func main() {
   var  ptr *int
   fmt.Printf("ptr The value of is : %x\n", ptr  )
}

result

ptr The value of is : 0

Then we generally judge the null pointer as

if(ptr != nil)     /* ptr Not a null pointer */
if(ptr == nil)    /* ptr Is a null pointer */

The above is the door where the old cat takes you into the pointer. Of course, it is also the introduction of the old cat. Later, we will slowly understand the usage of pointers in practical examples.

Value passing and reference passing

So what is value passing and what is reference passing? Let's briefly look at a piece of C + + code, as follows:

void pass_by_val(int a) {
   a++;
}
void pass_by_ref(int &a){
  a++;
}
int main(){
   int a = 3;
   pass_by_val(a);
   printf("After pass_by_val:%d\n",a);
   pass_by_ref(a);
   printf("After pass_by_ref:%d\n",a);
}

For the above two methods, one is value passing and the other is reference passing, what is the final output result? You can think about it first. In fact, the answer is 3 above and 4 below, so why?

Let's look at the first. The first is value transfer. In fact, the method of value transfer can be understood in the above example. The function copies the value in main into the function. Although 1 is added to the function, the original value of the outer layer is still 3, so the final output is still 3.

Let's take another look at reference passing. From the input parameter, in fact, the internal A and the external a refer to the same address. Therefore, when the internal function increases a, the value of the external function a changes to 4.

So is our GO value passing or reference passing? In fact, the GO language only has value passing.

You may be a little confused. In fact, many times, you don't have to worry too much, because in actual usage, we often solve relevant problems through the value of the function return.

Write at the end

Above, in fact, old cat shared with you the function definition of GO language and a more important concept of pointer. In the later study, we will experience it more deeply. Slowly deepen the impression in practice. Of course, I hope you can follow the example above and experience it while running. If you don't understand, you are welcome to communicate and make progress together.
I am a cat, more content. Welcome to search for official account of cat.

Posted by guttyguppy on Fri, 19 Nov 2021 16:13:16 -0800