go language learning record 3

Posted by JimStrosky on Fri, 28 Jan 2022 13:44:06 +0100

catalogue

go language pointer

Address:

Define pointer:

Use pointer:

Null pointer:

go language structure

Define structure

Access structure members

Structure as function parameter

Structure pointer

go language recursive function

Factorial:

Fibonacci sequence:

go language type conversion

go language interface

Relationship between interface and type

go error handling

go concurrency

channel

Channel buffer

go traverse and close channels

Learning material source: rookie tutorial

go language pointer

Address:

A variable is a convenient placeholder for referencing a computer's memory address.

The address fetching character of Go language is &. If it is used before a variable, the memory address of the corresponding variable will be returned.

Address of access variable in memory:

package main

import "fmt"

func main() {
   var a int = 10  

   fmt.Printf("Address of variable: %x\n", &a  )
}
/*
The code output result is:

Address of variable: 20818a220
*/

Define pointer:

A pointer variable points to the memory address of a value.

Like variables and constants, you need to declare pointers before using them.

The format of pointer declaration is as follows:

var var_name *var-type

(VaR type is the pointer type, var_name is the pointer variable name, and the * sign is used to specify that the variable is used as a pointer.)

Valid pointer declaration:

var ip *int / * points to integer*/
var fp *float32 / * point to floating point*/

Use pointer:

Pointer usage process:

  • Define pointer variables.
  • Assign values to pointer variables.
  • Access the value pointing to the address in the pointer variable.

(add a * sign (prefix) before the pointer type to get the content pointed to by the pointer.)

package main

import "fmt"

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

   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 )
}
/*
a The address of the variable is 20818a220
ip Pointer address of variable storage: 20818a220
*ip Value of variable: 20
*/

Null pointer:

When a pointer is defined and not assigned to any variable, 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:

package main

import "fmt"

func main() {
   var  ptr *int

   fmt.Printf("ptr The value of is : %x\n", ptr  )
}
//The value of ptr is: 0

Null pointer judgment:

If (PTR! = Nil) / * PTR is not a null pointer*/
If (PTR = = Nil) / * PTR is a null pointer*/

go language structure

In go language, we can define different data types for different items in the structure.

A structure is a data set composed of a series of data of the same type or different types.

Structure represents a record, such as the record of books in the library. Each book has the following attributes:

  • Title: title
  • Author: Author
  • Subject: subject
  • ID: Book ID

Define structure

Structure definition requires type and struct statements. The struct statement defines a new data type. There are one or more members in the structure. The type statement sets the name of the structure.

The format of the structure is as follows:

type struct_variable_type struct {
   member definition
   member definition
   ...
   member definition
}

Once the structure type is defined, it can be used for variable declaration. The syntax format is as follows:

variable_name := structure_variable_type {value1, value2...valuen}
or
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}

Example:

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}


func main() {

    // Create a new structure
    fmt.Println(Books{"Go language", "www.runoob.com", "Go Language course", 0})

    // You can also use the format key = > value
    fmt.Println(Books{title: "Go language", author: "www.runoob.com", subject: "Go Language course", book_id: 0})

    // The ignored field is 0 or empty
   fmt.Println(Books{title: "Go language", author: "www."})
}
/*
The output result is:

{Go Language www.go language tutorial 0}
{Go Language www.go language tutorial 0}
{Go Language: www.0}
*/

Access structure members

If you want to access structure members, you need to use a point number Operator, format:

Structure Member name“

Example:

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}

func main() {
   var Book1 Books        /* Declare Book1 as a Books type */
   var Book2 Books        /* Declare Book2 as a Books type */

   /* book 1 describe */
   Book1.title = "Go language"
   Book1.author = "www.0"
   Book1.subject = "Go Language course"
   Book1.book_id = 0

   /* book 2 describe */
   Book2.title = "Python course"
   Book2.author = "www.0"
   Book2.subject = "Python Language course"
   Book2.book_id = 0

   /* Print Book1 information */
   fmt.Printf( "Book 1 title : %s\n", Book1.title)
   fmt.Printf( "Book 1 author : %s\n", Book1.author)
   fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
   fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)

   /* Print Book2 information */
   fmt.Printf( "Book 2 title : %s\n", Book2.title)
   fmt.Printf( "Book 2 author : %s\n", Book2.author)
   fmt.Printf( "Book 2 subject : %s\n", Book2.subject)
   fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)
}
/*
Book 1 title : Go language
Book 1 author : www.
Book 1 subject : Go Language course
Book 1 book_id : 0
Book 2 title : Python course
Book 2 author : www.
Book 2 subject : Python Language course
Book 2 book_id : 0

Structure as function parameter

Pass the structure type as an argument to the function:

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}

func main() {
   var Book1 Books        /* Declare Book1 as a Books type */
   var Book2 Books        /* Declare Book2 as a Books type */

   /* book 1 describe */
   Book1.title = "Go language"
   Book1.author = "www."
   Book1.subject = "Go Language course"
   Book1.book_id = 0

   /* book 2 describe */
   Book2.title = "Python course"
   Book2.author = "www."
   Book2.subject = "Python Language course"
   Book2.book_id = 0

   /* Print Book1 information */
   printBook(Book1)

   /* Print Book2 information */
   printBook(Book2)
}

func printBook( book Books ) {
   fmt.Printf( "Book title : %s\n", book.title)
   fmt.Printf( "Book author : %s\n", book.author)
   fmt.Printf( "Book subject : %s\n", book.subject)
   fmt.Printf( "Book book_id : %d\n", book.book_id)
}
/*
The operation result is:

Book title : Go language
Book author : www.
Book subject : Go Language course
Book book_id : 0
Book title : Python course
Book author : www.
Book subject : Python Language course
Book book_id : 0
*/

Structure pointer

Defining a pointer to a structure is similar to other pointer variables. The format is as follows:

var struct_pointer *Books

Defining a pointer to a structure is similar to other pointer variables. The format is as follows:

var struct_pointer *Books

Use the structure pointer to access structure members, and use "." Operator:

struct_pointer.title

Example:

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}

func main() {
   var Book1 Books        /* Declare Book1 as a Books type */
   var Book2 Books        /* Declare Book2 as a Books type */

   /* book 1 describe */
   Book1.title = "Go language"
   Book1.author = "www."
   Book1.subject = "Go Language course"
   Book1.book_id = 0

   /* book 2 describe */
   Book2.title = "Python course"
   Book2.author = "www."
   Book2.subject = "Python Language course"
   Book2.book_id = 0

   /* Print Book1 information */
   printBook(&Book1)

   /* Print Book2 information */
   printBook(&Book2)
}
func printBook( book *Books ) {
   fmt.Printf( "Book title : %s\n", book.title)
   fmt.Printf( "Book author : %s\n", book.author)
   fmt.Printf( "Book subject : %s\n", book.subject)
   fmt.Printf( "Book book_id : %d\n", book.book_id)
}
/*
The execution and operation results of the above examples are as follows:

Book title : Go language
Book author : www.
Book subject : Go Language course
Book book_id : 0
Book title : Python course
Book author : www.
Book subject : Python Language course
Book book_id : 0
*/

go language recursive function

The syntax format of recursion (invoking itself in running) is as follows:

func recursion() {
recursion() / * function calls itself*/
}

func main() {
   recursion()
}

be careful:

Go language supports recursion. But when we use recursion, developers need to set exit conditions, otherwise recursion will fall into an infinite loop. In mathematics, recursive function can calculate factorial, generate Fibonacci sequence and so on.

Factorial:

Use examples to understand:

package main

import "fmt"

func Factorial(n uint64)(result uint64) {
    if (n > 0) {
        result = n * Factorial(n-1)
        return result
    }
    return 1
}

func main() {  
    var i int = 15
    fmt.Printf("%d The factorial of is %d\n", i, Factorial(uint64(i)))
}
/*
The execution output of the above example is:

15 The factorial of is 1307674368000
*/

Fibonacci sequence:

Example understanding:

package main

import "fmt"

func fibonacci(n int) int {
  if n < 2 {
   return n
  }
  return fibonacci(n-2) + fibonacci(n-1)
}

func main() {
    var i int
    for i = 0; i < 10; i++ {
       fmt.Printf("%d\t", fibonacci(i))
    }
}
/*
0    1    1    2    3    5    8    13    21    34
*/

go language type conversion

Type conversion is used to convert a variable of one data type to a variable of another type.

The basic format of Go language type conversion is as follows:

type_name(expression)

type_name is the type and expression is the expression.

example:

Convert an integer to a floating-point type, calculate the result, and assign the result to a floating-point variable.

package main

import "fmt"

func main() {
   var sum int = 17
   var count int = 5
   var mean float32
   
   mean = float32(sum)/float32(count)
   fmt.Printf("mean The value of is: %f\n",mean)
}
/*mean The value of: 3.400000*/

go language interface

Go language provides another data type, interface (a set of standards). It defines all common methods together. As long as any other type implements these methods, it implements this interface.

Interface features: only method declarations, no fields.

/*Define interface*/
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/*Define structure*/
type struct_name struct {
   /* variables */
}

/*Implementation interface method*/
func (struct_name_variable struct_name) method_name1() [return_type] {
/ * method implementation*/
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
/ * method implementation*/
}

package main

import (
    "fmt"
)

type Phone interface {
    call()
}

type NokiaPhone struct {
}

func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
}

func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}

func main() {
    var phone Phone

    phone = new(NokiaPhone)
    phone.call()

    phone = new(IPhone)
    phone.call()

}
/*
The output results are as follows:

I am Nokia, I can call you!
I am iPhone, I can call you!
*/

In the above example, we defined an interface Phone, which has a method call(). Then we define a Phone type variable in the main function and assign it to Nokia Phone and IPhone respectively. Then we call the call() method.

Relationship between interface and type

One type can implement multiple interfaces (moile can be playusic and playvideo)

Multiple types can implement the same interface (cats and dogs are pets and can eat)

go error handling

Error type is an interface type. Error information is generated by implementing the error interface type in coding.

definition:

type error interface {
    Error() string
}

Functions usually return error information in the last return value. Use errors New returns an error message:

package main

import (
    "fmt"
)

// Define a DivideError structure
type DivideError struct {
    dividee int
    divider int
}

// Implement the 'error' interface
func (de *DivideError) Error() string {
    strFormat := `
    Cannot proceed, the divider is zero.
    dividee: %d
    divider: 0
`
    return fmt.Sprintf(strFormat, de.dividee)
}

// Define the function of division operation of type 'int'
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
    if varDivider == 0 {
            dData := DivideError{
                    dividee: varDividee,
                    divider: varDivider,
            }
            errorMsg = dData.Error()
            return
    } else {
            return varDividee / varDivider, ""
    }

}

func main() {

    // Normal condition
    if result, errorMsg := Divide(100, 10); errorMsg == "" {
            fmt.Println("100/10 = ", result)
    }
    // An error message is returned when the divisor is zero
    if _, errorMsg := Divide(100, 0); errorMsg != "" {
            fmt.Println("errorMsg is: ", errorMsg)
    }

}
/*
The output result is:

100/10 =  10
errorMsg is:  
    Cannot proceed, the divider is zero.
    dividee: 100
    divider: 0
*/

go concurrency

Go language supports concurrency. We only need to open goroutine through the go keyword.

Goroutine is a lightweight thread, and the scheduling of goroutine is managed by the Golang runtime.

goroutine syntax format:

go function name (parameter list)

Go allows you to use the go statement to start a new runtime thread, goroutine, to execute a function with a different, newly created goroutine. All goroutines in the same program share the same address space.

channel

A channel is a data structure used to transfer data.

Channel can be used for synchronous operation and communication between two goroutine s by passing a specified type of value. Operator < - used to specify the direction of the channel, send or receive. If no direction is specified, it is a two-way channel.

ch < - v / / send v to channel ch
 V: = < - ch / / receive data from ch
           //And assign the value to v

It's easy to declare a channel. We can just use the chan keyword. The channel must be created before use:

ch := make(chan int)

Note: by default, channels are unbuffered. The sending end sends data, and there must be corresponding received data at the receiving end.

Example:

Calculate the sum of numbers through two goroutines. After goroutine completes the calculation, it will calculate the sum of the two results:

package main

import "fmt"

func sum(s []int, c chan int) {
        sum := 0
        for _, v := range s {
                sum += v
        }
        c <- sum // Send sum to channel c
}

func main() {
        s := []int{7, 2, 8, -9, 4, 0}

        c := make(chan int)
        go sum(s[:len(s)/2], c)
        go sum(s[len(s)/2:], c)
        x, y := <-c, <-c // Receive from channel c

        fmt.Println(x, y, x+y)
}
/*
The output result is:

-5 17 12
*/

Channel buffer

The channel can set the buffer, and specify the buffer size through the second parameter of make:

ch := make(chan int, 100)

The channel with buffer allows the data transmission of the sender and the data acquisition of the receiver to be in an asynchronous state, that is, the data sent by the sender can be placed in the buffer and can wait for the receiver to obtain the data, rather than requiring the receiver to obtain the data immediately.

However, because the size of the buffer is limited, there must be a receiver to receive data. Otherwise, as soon as the buffer is full, the data sender cannot send data again.

Note: if the channel is not buffered, the sender will block until the receiver receives the value from the channel. If the channel is buffered, the sender will block until the transmitted value is copied into the buffer; If the buffer is full, it means waiting until a receiver gets a value. The receiver will be blocked until there is a value to receive.

package main

import "fmt"

func main() {
    // Here we define a buffered channel that can store integer types
        // The buffer size is 2
        ch := make(chan int, 2)

        // Because ch is a buffered channel, we can send two data at the same time
        // You don't need to read data synchronously immediately
        ch <- 1
        ch <- 2

        // Get these two data
        fmt.Println(<-ch)
        fmt.Println(<-ch)
}
/*
The execution output is:

1
2
*/

go traverse and close channels

Go traverses the read data through the range keyword, which is similar to array or slice. The format is as follows:

v, ok := <-ch
package main

import (
        "fmt"
)

func fibonacci(n int, c chan int) {
        x, y := 0, 1
        for i := 0; i < n; i++ {
                c <- x
                x, y = y, x+y
        }
        close(c)
}

func main() {
        c := make(chan int, 10)
        go fibonacci(cap(c), c)
        // The range function iterates over the data received from each channel, because c is sending 10
        // After the data, the channel is closed, so here our range function receives 10 data
        // Then it's over. If the c channel above is not closed, the range function is not closed
        // Will end, blocking when receiving the 11th data.
        for i := range c {
                fmt.Println(i)
        }
}
/*
The execution output is:

0
1
1
2
3
5
8
13
21
34
*/

Topics: Go Back-end