Go Basics

Go

vscode configuring go development environment

1. Download vscode

https://code.visualstudio.com/

2. Install sdk

https://golang.google.cn/dl/
After entering this interface, find the corresponding version go version. windows-amd64.zip

The installation path cannot have Chinese or special symbols

3. Test whether the sdk installation is successful

In the bin directory

go version enter

Output go version go version windows/amd64

4. Configure golang environment variables

1. New system variable

Variable name: GOROOT

Variable value: directory of sdk

2. Edit Path variable by system variable

Create a new% GOROOT%\bin in the Path variable

3. System variable create a GOPATH variable

This variable is the path where the go project is stored, and its location is determined by itself

Example: D:\goproject

go directory structure

goproject

src

go_code
project01
project02
project03

Then, there are main and package under each project

Describe the catalog

go file suffix

Yes. go

package main

Indicates that the package where the hello.go file is located is main. In go, each file must belong to a package

impor "fmt"

Indicates the introduction of a package named FMT. After the introduction, you can use the functions of FMT package, such as fmt.Println

funcmain(){}

func is a keyword that represents a function. Main is the function name. It is a main function, that is, the entry of our program.

fmt.Println("hello")

Means calling the function Println of fmt package and outputting "hello,world"

gobuild

Compile the go file through this command to generate an. exe file

Just run the hello.exe file

gorun

Note: you can directly run the hello.go program through this command

But it is not standardized and needs to compile the source code, which is very slow

[similar to executing a script file]

vscode common errors

The "go-outline" command is not available. Run "go get -v github.com/ramya-r

resolvent:

Use win+R to enter cmd and enter the following command line:

// Turn on proxy settings
go env -w GO111MODULE=on

// Set proxy source
go env -w GOPROXY=https://goproxy.io,direct

Restart VScode, open The created go file, and when prompted again The "go outline" command is not available. Run "go get -v github.com/ramya-r, directly click install all and wait for The installation.

package main burst red

go: go.mod file not found in current directory or any parent directory; see 'go help modules'

go env -w GO111MODULE=auto

Restart vscode problem resolution

go Foundation

  • The go source file takes ". Go" as the extended name
  • The execution entry is the main function
  • Strictly case sensitive
  • The go method consists of statements, and each statement does not need a semicolon (go is automatically added)
  • Write multiple statements on one line, separated by semicolons
  • If the variables defined by go or the package of import are not used, the code cannot be compiled
  • Braces appear in pairs

Escape character

  • \t: Represents a tab that is usually used for typesetting.

  • \n: Newline character

  • \: one\

  • \"·: one"

  • \r: One enter fmt.Println("Tianlong Babu snow mountain flying fox \ r Zhang Fei");

    This output is Zhang Fei's eight snow mountain flying foxes

    Because this is different from line feed, after entering, it just continues to cover the output from the beginning, that is, Zhang Fei covers the original Tianlong

But this is not the case in vscode. Golan and they are not the same

notes

  • Single line note//

  • multiline comment

    /*

    Note content

​ */

(Note: shift+tab cancels the non indentation of unordered list)

api Chinese document

https://studygolang.com/pkgdoc

variable

Variable = variable name + value + data type

format

var variable name data type

Example:

var num int

If you assign directly, you can omit the type

For example:

var num=10

Attention

1. Default value

After specifying the variable type declaration, if no assignment is made, the default value will be used. For example, the default value of int is 0

2. Type derivation

After assignment, the variable type will be determined by itself according to the value

Example:

var num=10

3. Omit var

Omit var, the variable on the left of: = cannot be declared

name:="tom"     

This is equivalent to

var name string      
name="tom"

4. Multivariable declaration

Three ways

var n1,n2,n3 int

var n1,name,n3=100,"tom",555

n1,name,n3:=100,"tom",666

5. Global variables

Declare multiple global variables at once

Example:

var n1=100

var n2=200

var name="jack"

Change to one-time statement

var(

​	n1=100

​	n2=200

​	name="jack"

)

6. Reassign

A variable can be reassigned under its scope, but its type cannot be changed

data type

Basic introduction

Integer:

int,int8,int16,int32,int64,uint,uint8,uint16,uint32,uint64,byte

Floating point number:

float32,float64

character:

There is no special character type. Use byte to save single alphabetic characters

Boolean:

bool

character string:

string

Derived / complex data types:

Pointer, array, structure, pipe, function, slice, interface, map

I'll talk about it in detail later

Default value of basic data type

Integer: 0

Floating point: 0

String: ''

Boolean type: false

Mutual conversion of basic data types

Unlike java/c, Golang requires explicit conversion when assigning values between variables of different types. That is, data types in Golang cannot be automatically converted.

formula

Expression T(v) converts value v to type T

T: data types, such as int32, int64, float32, etc

v: is the variable to be converted

give an example

var i int32=100
//Change i to float type
var n=float32(i)

matters needing attention

  1. In Go, the conversion of data types can be from small range - > large range, or large range - > small range
  2. What is converted is the data (i.e. value) stored in the variable. The data type of the variable itself has not changed!
  3. For example, when converting int64 to int8 [- 128-127], no error will be reported during compilation, but the conversion result is treated as overflow, which is different from the desired result. Therefore, the range needs to be considered during conversion

To string type

Mode 1:

fmt.Sprintf("% parameter", expression)

The parameter needs to match the data type of the expression

fmt.Sprintf()... Will return the converted string

var num1 int=99
var num2 float64=23.456
var b bool=true
var c byte='h'
var str string

//transformation
str=fmt.Sprintf("%d",num1)

str=fmt.Sprintf("%f",num2)

str=fmt.Sprintf("%t",b)

str=fmt.Sprintf("%c",c)

//verification
fmt.Printf("str type %T str=%q",str,str)
//Each of the above can be verified after conversion
Mode 2:

Functions of strconv package

var num3 int=99
var num4 float64=23.456
var b2 bool=true

str=strconv.FormatInt(int64(num3),10)
//10: Converted base

str=strconv.FormatFloat(num4,'f',10,64)
//'f' format 10: 10 decimal places reserved 64: decimal places are double precision

str=strconv.FormatBool(b2)

//There is also an Itoa function that converts a number to a number of the corresponding string type.
//Example:
var num5 int64=4567
str=strconv.Itoa(int(num5))

string to basic data type

var str string = "true"
var b bool
// b, _ = strconv.ParseBool(str)
// explain:
// 1. The strconv.ParseBool(str) function returns two values (value bool, err, error)
// 2. Because I only want to get value bool, not err, I use - ignore
b,_ = strconv.ParseBool(str)
fmt.Printf("b type %T b=%v\n", b, b)

//----------------------------------------------
//----------------------------------------------

var str2 string = "1234590"
var n1 int64
var n2 int
n1,_ = strconv.ParseInt(str2, 10, 64)
//10: Converted base
//64: returned int type
n2 = int(n1)
fmt.Printf("n1 type %T n1=%v\n", n1, n1)
fmt.Printf("n2 type %T n2=%v\n", n2, n2)

//----------------------------------------------
//----------------------------------------------

var str3 string = "123.456"
var f1 float64
f1,_ = strconv.ParseFloat(str3, 64)
fmt.Printf("f1 type %T f1=%v\n", f1, f1)

//----------------------------------------------
//----------------------------------------------

//There is also an atoi function that converts a string into a corresponding number
i,_ := strconv.Atoi(s)

Because we returned int64 or float64 above, we need to convert it ourselves to get int32 or float32

Int32 (return value) or float (return value)

matters needing attention

When converting a String type to a basic data type, ensure that the String type can be converted to valid data. For example, we can convert "123" to an integer, but we can't convert "hello" to an integer. If we do so, Golang will directly convert it to 0. The same is true for other types. Float = > 0 bool = > false

Integer type

Difference in storage space and table number range between signed and unsigned types

byte for storing characters

Signed and unsigned, the size of int and uint is related to the system

Golang shaping is declared as int by default

such as

var n=100  // The type of n is int

unsafe.sizeof

Check the byte size and data type of a variable in the program

Keep small but not big

When using integer variables in Golang program, the principle of keeping small but not large shall be observed, that is, under the condition of ensuring the correct operation of the program, try to use data types with small space

For example:

var age byte=90

bit: the smallest storage unit in a computer. byte: the basic storage unit in a computer.

Let's go into more detail

​ 1byte=8bit

Floating point type

Single precision: float32

Double precision: float64

Storage form

A brief description of the storage form of floating point numbers in the machine. Floating point numbers = sign bit + exponential bit + trailing digit Description: floating point numbers are signed

Accuracy loss

The mantissa may be lost, resulting in loss of accuracy

Description:

The accuracy of float64 is more accurate than that of float32. Note: if we want to save a high-precision number, we should choose float64

details

  1. The Golang floating point type has a fixed range and field length and is not affected by the specific OS (operating system)

  2. The floating point type of Golang is declared as float64 by default.

  3. Floating point constants have two representations

    Decimal form:

    For example: 5.12. 512 (must have decimal point). 512 is 0.512

    Scientific counting method form:

    For example, 5.1234e2=5.12*10 to the second power, 5.12E-2=5.12/10 to the second power

  4. In general, float64 should be used because it is more accurate than float32.

Character type

  1. There is no special character type in Golang. If you want to store a single character (letter), you usually use byte to save it.
  2. A string is a sequence of characters connected by a string of fixed length characters.
  3. The string of Go is connected by a single byte, that is, for the traditional string, it is composed of characters, while the string of Go is different, it is composed of bytes.

give an example

  1. If the saved characters are in the ASCII table, such as [0-1,a-z,A-Z...], they can be directly saved to byte
  2. If the corresponding code value of the saved character is greater than 255, we can consider saving it with int type
  3. If we need to install character output, we need to format the output, that is, fmt.Printf("% c", c1)

details

  1. A character constant is a single character enclosed in single quotation marks ('). For example,' varc3byte = '9' in varc1byte='a 'varc2int ='
  2. The escape character '\' is allowed in Go to convert subsequent characters into special character type constants. For example, varc3char = '\ n' / / '\ n' indicates a line break
  3. The characters of Go language are encoded in UTF-8. If you want to query the utf8 code value corresponding to the characters http://www.mytju.com/classcode/tools/encode_utf8.asp English letter - 1 byte Chinese character - 3 bytes
  4. In Go, the essence of a character is an integer. When directly output, it is the code value of UTF-8 encoding corresponding to the character.
  5. You can directly assign a number to a variable, and then press format. When%c, the unicode character corresponding to the number will be output
  6. The character type can be operated, which is equivalent to an integer, because it all corresponds to Unicode code

essence

  1. When the character type is stored in the computer, the code value (integer) corresponding to the character needs to be found

    Storage: character - > corresponding code value - > binary - > storage

    Read: binary ---- > code value ---- > character – > read

  2. The correspondence between characters and code values is determined through the character coding table (it is specified)

  3. The coding of Go language is unified into utf-8. It is very convenient and unified. There is no trouble of coding disorderly code anymore

Boolean type

  1. Only true or false is allowed
  2. Occupy one byte

String type

A string is a sequence of characters connected by a string of fixed length characters. Go strings are connected by a single byte. The bytes of go language strings use UTF-8 encoding to identify Unicode text

details

  1. The bytes of the string of Go language use UTF-8 encoding to identify Unicode text, so that Golang uses UTF-8 encoding uniformly, and the problem of Chinese garbled code will no longer bother programmers.
  2. Once the string is assigned, the string cannot be modified: in Go, the string is immutable.

Representation

  1. Double quotation marks that recognize escape characters
  2. Backquotes are output in the native form of strings, including line breaks and special characters, which can prevent attacks and output source code

String splicing

var str="hello"+"world"
str+="haha"

When splicing long strings, you can wrap lines, but the end of the line must be a + sign

Pointer

Storage address

Get the address of the variable. Use &, such as var num int, to get the address of num: & num

var ptr *int=&num
//*ptr dereference gets the value of the address

details

  1. Value types have corresponding pointer types in the form of data types. For example, the pointer corresponding to int is int, the pointer corresponding to float32 is * float32, and so on.
  2. Value types include: basic data types, int series, float series, bool,string, array and struct

Value type and reference type

  1. Value types: basic data types: int series, float series, bool,string, array and struct
  2. Reference type: pointer, slice slice, map, pipe chan, interface, etc. are all reference types

characteristic

  1. Value type: variables store values directly, and memory is usually allocated in the stack

  2. Reference type: a variable stores an address. Only the space corresponding to this address can really store data (values). Memory is usually allocated on the heap. When no variable references this address, the data space corresponding to this address becomes garbage and is recycled by GC

  3. Stack area: value type data, usually in the stack area

    Heap: a reference type that usually allocates space in the heap

identifier

  1. It is composed of 26 English letters, upper and lower case, 0-9
  2. Number cannot start
  3. Strict case sensitivity in Golang
  4. The identifier cannot contain spaces
  5. The underscore "" itself is a special identifier in Go, called null identifier. It can represent any other identifier, but its corresponding value will be ignored (for example, ignoring a return value). Therefore, it can only be used as a placeholder, not as an identifier
  6. The system reserved keywords cannot be used as identifiers (there are 25 in total), such as break, if, etc

be careful:

int//ok, we ask you not to use it like this
float32//ok, we ask you not to use it like this

Naming considerations

  1. Package name: keep the package name and directory consistent. Try to use meaningful package names, which are short and meaningful. Do not conflict with the standard library fmt

  2. Variable name, function name and constant name: hump method is adopted, for example:

    var stuName string = "tom" form: xxxYyyyyZzzz

    var goodPrice float32=1234.5

  3. If the variable name, function name and constant name are capitalized, they can be accessed by other packages; if they are lowercase, they can only be used in this package

    (Note: it can be simply understood that uppercase is public and lowercase is private) there are no public,private and other keywords in golang

The system reserves keywords and predefined identifiers

Baidu itself may change at any time

operator

Arithmetic operator

+,-,*,/,%,++,–

Note%:

fmt.Println("10%3=",10%3)//=1

fmt.Println("-10%3=",-10%3)
//=-10-(-10)/3*3=-10-(-9)=-1

fmt.Println("10%-3=",10%-3)//=1

fmt.Println("-10%-3=",-10%-3)//=-1

matters needing attention

  1. For the division sign "/", there is a difference between integer division and decimal division: when dividing between integers, only the integer part is retained and the decimal part is discarded. For example, x:=19/5, the result is 3

  2. When a number is modulo, it can be equivalent to a%b=a-a/b*b, so we can see an essential operation of modulo

  3. Golang's self increasing and self decreasing can only be used as an independent language

    You can't do this:

    a=i++
    a=i--
    if(i++>0)
    //All three are wrong
    
  4. The + + and – of Golang can only be written after the variable, not before the variable, that is, only a++a – no + + a – a

    No pre + + and –

  5. The designers of Golang removed the confusing writing method of self increase and self decrease in c/java to make Golang more concise and unified. (mandatory)

Relational operator

== ,!= ,< ,> ,<= ,>=

Logical operator

&& , || , ! (logical non operator)

be careful:

  1. &&Also called short circuit and: if the first condition is false, the second condition will not be judged, and the final result is false
  2. ||Also called short circuit or: if the first condition is true, the second condition will not be judged, and the final result is true

Assignment Operators

=, +=, -=, *=, /=, %=

Let's talk about the following in binary

<<=, >>=, &=, ^=, |=

Bitwise Operators

&, |, ^, <<, >>

Also in binary

Other Operators

&: returns the address of the variable store

*: pointer variable

Go does not support ternary operators

//Traditional ternary operation
n=i>j?i:j

//Go in
if i>j{
	n=i
}else{
	n=j
}

Operator priority

1: Parentheses, + +, –

2: Monocular operation

3: Arithmetic operator

4: Shift operation

5: Relational operator

6: Bitwise operator

7: Logical operator

8: Assignment operator

9: Comma

keyboard entry

Call fmt.Scanln() or fmt.Scanf() of fmt package

Mode 1:

var name string
var age byte
var sal float32
var isPass bool

fmt.Scanln(&name)

fmt.Scanln(&age)

fmt.Scanln(&sal)

fmt.Scanln(&isPass)

Mode 2:

fmt.Scanf("%s %d %f %t",&name,&age,&sal,&isPass)

Base system

Another blog record is inserted into a directory

Program flow control

judge

if Expression 1{
    Execution 1
}else if Expression 2{
    Execution 2
}else{
    Perform other
}

if expression cannot be an assignment statement

switch

There is no need to break in golang

  1. The execution process of switch is to execute the expression to obtain the value, and then compare it with the case expression. If it is equal, it will match, then execute the corresponding case statement block, and then exit the switch control.
  2. If the value of the switch expression does not match the expression of any case successfully, the default statement block is executed. Exit switch after execution
  3. There can be multiple expressions after the case of golang, separated by commas
  4. The case statement block in golang does not need to write break, because there will be break by default, that is, by default, when the program finishes executing the case statement block, it will directly exit the switch control structure.
switch expression{
	case Expression 1, expression 2,...:
		Execute statement 1
	case Expression 3, expression 4,...:
		Execute statement 2
	case ...:
		...
	default:
		Execute statement
}

be careful:

  • case/switch is followed by an expression (that is, constant value, variable, a function with return value, etc.)
  • The data type of the value of each expression after case must be consistent with the expression data type of switch
  • Case can be followed by multiple expressions, separated by commas. For example, case expression 1, expression 2
  • If the expression after case is a constant value (literal), it must not be repeated
  • The case does not need to be followed by a break. After the program matches a case, it will execute the corresponding code block, and then exit the switch. If none of them match, it will execute default
  • The default statement is not required
  • It can also be used without an expression after switch, similar to the if – else branch
var age int = 10

switch{
    case age==10:
    	fmt.Println...
    case age==20:
    	fmt.Println...
    default:
    	....
}
  • You can also directly declare / define a variable after the switch. It ends with a semicolon. It is not recommended.
switch grade:=90{
    case grade>=90:
    	..
	...
}
  • Switch penetration - fallthrough. If fallthrough is added after the case statement block, the next case will continue to be executed, which is also called switch penetration (the default penetration level)
var age int = 10

switch{
    case age==10:
    	fmt.Println...
    	fallthrough
    case age==20:
    	fmt.Println...
    	fallthrough
    default:
    	....
}
  • TypeSwitch: the switch statement can also be used for type switch to judge the type of variable actually pointed to in an interface variable (experience it first before learning interface)
var x interface{}
var y=10.0
x=y
switch i:=x.(type){
    case nil:
    	fmt.Printf("x The type of is:%T",i)
	case int:
    	fmt.Printf("x The type of is int type")
    ...
}

switch and if comparison

  1. If there are few specific values to judge, and they conform to integer, floating point number, character and string types. It is recommended to use swtich statement, which is concise and efficient.
  2. Other situations: for interval judgment and judgment with bool result, if is used. If is used in a wider range.

for

Mode 1:

for i:=1;i<=10;i++{
    fmt.Println("hello world",i)
}

Mode 2:

	i:=1
	for i<=10{
		fmt.Println("hello world",i)
		i++
	}

Mode 3:

//Dead cycle
for{
    Execute statement
}

//This writing method is equivalent to the following, which is usually used in conjunction with if and break statements
for ; ;{
    
}

A loop condition is an expression that returns a Boolean value

Golang provides a for range method to easily traverse strings and arrays (Note: the traversal of arrays will be explained later when we talk about arrays). The case shows how to traverse strings

Mode 1:

var str string="hello world"
for i:=0;i<len(str);i++{
	fmt.Printf("%c",str[i])
}

Method 2: for range

var str string="hello world"
for index,val:=range str{
    fmt.Printf("index=%d,val=%c",index,val)
}

be careful:

If our string contains Chinese, the traditional way of traversing the string is an error and garbled code will appear. The reason is that the traditional traversal of strings is based on bytes, while a Chinese character corresponds to three bytes in utf8 coding.

How to solve it? You need to convert str to a [] run slice

var str string="hello world,Beijing"
	str2:= []rune(str)
	for i:=0;i<len(str2);i++{
		fmt.Printf("%c ",str2[i])
	}

However, for the for range traversal mode, it is traversed in character mode. Therefore, if a string has Chinese, it is ok

var str string="hello world,Beijing"
	for index,val:=range str{
		fmt.Printf("index=%d,val=%c\n",index,val)
	}

Go language has no while and do... While syntax, which requires students' attention. If we need to use other languages (such as java/c while and do... while), we can use the for loop to achieve its use effect.

continue

  1. The continue statement is used to end this loop and continue to execute the next loop.
  2. When the continue statement appears in the body of a multi-level nested loop statement, you can indicate which level of loop to skip through the label, which is the same as the rule used in the previous break label

goto

  1. The goto statement of Go language can unconditionally transfer to the specified line in the program.
  2. goto statements are usually used in conjunction with conditional statements. It can be used to realize conditional transfer, jump out of the loop body and other functions
  3. In Go programming, goto statement is generally not advocated to avoid confusion of program flow and difficulties in understanding and debugging the program
goto label:
...
label:statement

Example:

var n = 30
if n >20{
    goto label2
}
fmt.Println("1")
fmt.Println("2")
fmt.Println("3")
label2:
fmt.Println("4")
fmt.Println("5")
fmt.Println("6")

return

  1. return when used in a method or function, it means to jump out of the method or function. It will be introduced in detail when explaining the function
  2. If return is an ordinary function, it means that the function jumps out, that is, the code behind return in the function is no longer executed, which can also be understood as terminating the function.
  3. If return is in the main function, it means that the main function is terminated, that is, the program is terminated.

package

  • In actual development, we often need to call the functions defined in other files in different files, such as main.go. How to use the functions in utils.go file? - > package
  • Now two programmers jointly develop a Go project. Programmer xiaoming wants to define the function Cal, and programmer xiaoqiang also wants to define the function, also known as Cal. Two programmers quarreled about this. What should we do? - > package
  • Each file of go belongs to a package, that is, go manages the file and project directory structure in the form of package

The essence of a package is to create different folders to store program files

effect

  1. Identifiers that distinguish functions, variables, etc. with the same name
  2. When there are many program files, you can manage the project well
  3. Control the access scope of functions and variables, i.e. scope

explain

  • Basic packing syntax: package package name

  • Basic syntax of importing package: import "path of package"

details

  1. When packaging a file, the package corresponds to a folder. For example, the package name corresponding to the utils folder here is utils. The package name of the file is usually the same as the folder name where the file is located, usually in lowercase letters.

  2. When a file needs to use other package functions or variables, the corresponding package needs to be introduced first

    Introduction method 1:

    import "Package name
    

    Introduction method 2:

    import (
    
    	"Package name
    
    	"Package name	
    
    )
    

    The package directive is on the first line of the file, followed by the import directive.

    When importing the package, the path starts from src of $GOPATH. Without src, the compiler will automatically import it from src

  3. In order for files in other packages to access functions in this package, the first letter of the function name must be capitalized, similar to public in other languages, so that it can be accessed across packages.

  4. When accessing other package functions and variables, the syntax is package name. Function name

  5. If the package name is long, Go supports aliasing the package. Pay attention to the details: after aliasing, the original package name cannot be used

  6. Under the same package, you cannot have the same function name (nor the same global variable name), otherwise you will be reported as having duplicate definitions

  7. If you want to compile into an executable program file, you need to declare the package as main, that is, packagemain. This is a syntax specification. If you write a library, the package name can be customized

function

func Function name (parameter list ) (Return value list) {

		Execute statement..

		return Return value list

}

Functions can also have no return value

Example: simple calculator

func Cal(n1 float64,n2 float64,operator byte) float64{
    var res float64
    switch operator{
        case '+':
        	res=n1+n2
        ...
        default:
        	fmt.Println("Operator error")
    }
    return res
}

details

  1. When calling a function, a new space will be allocated to the function, and the compiler will distinguish this new space from other stack spaces through its own processing
  2. In the stack corresponding to each function, the data space is independent and will not be confused
  3. When a function is called (executed), the program will destroy the stack space corresponding to the function.

return

The Go function supports returning multiple values

func Function name (parameter list ) (Return value type list){
    sentence..
    return Return value list
}
  • When multiple returned values are received, if you want to ignore a return value, use_
  • If there is only one return value, the parentheses in the return value type list can be omitted, that is, write the type directly

Example:

func getSumAndSub(n1 int,n2 int) (int,int){
    sum:=n1+n2
    sub:=n1-n2
    return sum,sub
}

func main(){
    ret1,ret2:=getSumAndSub(1,2)
    fmt.Printf("ret1=%v,ret2=%v",ret1,ret2)
    //If you want to ignore a return value
    _,res3=getSumAndSub(1,2)
    fmt.Printf("ret3=%v",ret3)
}

matters needing attention

  1. The formal parameter list of a function can be multiple, and the return value list can also be multiple.
  2. The data types of formal parameter list and return value list can be value type and reference type.
  3. The naming of the function follows the identifier naming standard. The first letter cannot be a number. The first letter is uppercase. The function can be used by this package file and other package files, similar to public. The first letter is lowercase. It can only be used by this package file. Other package files cannot be used, similar to priva
  4. The variables in the function are local and do not take effect outside the function
  5. Basic data types and arrays are passed by value by default, that is, value copying. Modification in the function will not affect the original value
  6. If you want the variables inside the function to modify the variables outside the function (referring to the data type passed by value by default), you can pass in the address &, and operate the variables in the function in the form of pointers. In effect, similar references
  7. The Go function does not support function overloading
  8. In Go, a function is also a data type. If it can be assigned to a variable, the variable is a function type variable. This variable allows you to call a function
func getSumAndSub(n1 int,n2 int) (int,int){
    sum:=n1+n2
    sub:=n1-n2
    return sum,sub
}

func main(){
    a:=getSumAndSub
    res1,res2:=a(1,2)
    //Equivalent to res1,res2:=getSumAndSub(1,2)
}
9. Since the function is a data type, the Go In, a function can be used as a formal parameter and called
10. To simplify data type definition, Go Support custom data types
Basic syntax: type Custom data type name data type //Understanding: equivalent to an alias
 Case 1: type myInt int  //At this time, myInt is equivalent to int

Case 2: type mySum func(int,int) int
//At this time, mySum is equivalent to a function type func(int,int)int
11. Support naming function return value
12. use_Identifier, ignoring return value
13. Go Support variable parameters
//0 to more than one parameter is supported
func sum(args...int)sum int{
}

//Support 1 to more parameters
func sum(n1 int,args...int)sum int{
}
  • Args is slice slice, and each value can be accessed through args[index]
  • If there are variable parameters in a function's formal parameter list, the variable parameters need to be placed at the end of the formal parameter list
  • Example:
//Calculates the sum of 1 to more int s
func sum(n1 int,args...int)int{
    sum:=n1
    for i:=0;i<len(args);i++{
        sum+=args[i]
    }
    return sum
}

Small case:

type mySum func (int, int) int

func sum(n1 int, n2 int) int{
	return n1+n2
}

func sum2(n1,n2, n3 int) int {
	return n1 +n2
}

//Use type to customize data types to simplify definitions
func myFunc(funcVar mySum, num1 int, num2 int) int {
	return funcVar(num1, num2)
}

func main(){
	a := sum
	b := sum2
	fmt.println(myFunc(a,1,2))//ok
	fmt.PrintIn(myFunc(b,1,2)) //error
}

//Are there any errors in the code and why?
//fmt.Println(myFunc(b, 1,2) error
//The reason is the type mismatch. Because func sum2 (N1, N2, N3, int) int cannot be assigned to func (int, int)int

recursion

A function calls itself in the function body, which is called recursive call

cardinal principle

  1. When a function is executed, a new protected independent space (new function stack) is created
  2. The local variables of the function are independent and will not affect each other
  3. Recursion must approach the condition of exiting recursion, otherwise it is infinite recursion
  4. When a function is executed or returns, it will be returned. The result will be returned to whoever calls it. At the same time, when the function is executed or returned, the function itself will be destroyed by the system

init function

Each source file can contain an init function, which will be called by the Go running framework before the main function is executed, that is, init will be called before the main function

details

  1. If a file contains global variable definitions, init function and main function at the same time, the executed process global variable definitions - > init function - > main function
  2. The main function of init function is to complete some initialization
  3. If both main.go and utils.go contain variable definitions, what is the process of executing the init function?
main.go
import ".../utils"

Variable definition  //3

init function  //4

main function  //5

//***********
utils.go

Variable definition  //1

init function  //2

Anonymous function

Go supports anonymous functions. Anonymous functions are functions without names. If we want to use a function only once, we can consider using anonymous functions. Anonymous functions can also be called multiple times.

use

Mode 1:

The anonymous function can be called directly when it is defined. In this way, the anonymous function can only be called once

func main(){
    res1:=func(n1 int,n2 int)int{
        return n1+n2
    }(10,20)
    fmt.Println("res1=",res1)
}

Mode 2:

Assign an anonymous function to a variable (function variable), and then call the anonymous function through the variable

a:=func(n1 int,n2 int)int{
    return n1-n2
}

res2:=a(10,30)
fmt.Println("res2=",res2)

res3:=a(20,60)
fmt.Println("res3=",res3)

Global anonymous function

If you assign an anonymous function to a global variable, the anonymous function becomes a global anonymous function and can be effective in the program.

var(
    Fun1=func(n1 int,n2 int)int{
        return n1*n2
    }
)
res4:=Fun1(4,9)
fmt.Println("res4=",res4)

closure

A closure is a combination of a function and its associated reference environment

case

func addupper() func (int) int{
	var a =10
	return func(n int) int {
		a=a+n
		return a
	}
}

func main(){
	f:=addupper()
	fmt.Println(f(1))
	fmt.Println(f(3))
	fmt.Println(f(5))
}
  1. addupper is a function that returns a data type of fun (int) int

  2. Description of closure:

    An anonymous function is returned, but the anonymous function refers to n outside the function. Therefore, the anonymous function forms a whole with n to form a closure.

  3. It can be understood as follows: a closure is a class, a function is an operation, and N is a field. A function and its use to n constitute a closure

  4. When we call f function repeatedly, because n is initialized once, it is accumulated every time we call it

  5. The key to making a closure clear is to analyze which variables the returned function uses (references), because the function and the variables it references together constitute a closure

practice

  1. Write a function makeSuffix(suffixstring) to receive a file suffix (such as. jpg) and return a closure
  2. Call the closure to pass in a file name. If the file name does not have a specified suffix (such as. jpg), the file name. jpg will be returned. If there is already a. jpg suffix, the original file name will be returned
  3. Closure is required
  4. strings.HasSuffix, which can determine whether a string has a specified suffix
func makesuffix(suffix string) func (string) string{
	return func(name string) string {
		if !strings.HasSuffix(name,suffix){
			return name+suffix
		}
		return name
	}
}

func main(){
	f:=makesuffix(".jpg")
	fmt.Println(f("winter"))   //winter.jpg
	fmt.Println(f("spring.jpg"))  //spring.jpg
}

Above program description

  1. The returned anonymous function is combined with the suffix variable of makesuffix (suffix string) to form a closure, because the returned function refers to the suffix variable
  2. Let's experience the benefits of closures. If we use traditional methods, we can easily realize this function, but the traditional methods need to pass in the suffix every time, such as. jpg. Because closures can retain a value referenced last time, we can pass it in once and use it again

defer of function

In functions, programmers often need to create resources (such as database connection, file handle, lock, etc.). In order to release resources in time after the function is executed, Go designers provide defer (delay mechanism)

func sum(n int,m int){

	defer fmt.Println("----",n)
	defer fmt.Println("****",m)

	fmt.Println("And are:",n+m)
}

func main(){
	sum(1,2)
}

//Results ↓

/*
Sum: 3
**** 2
---- 1
*/

details

  1. When go executes a defer, it will not execute the statement after defer immediately, but press the statement after defer into a stack [temporarily called defer stack], and then continue to execute the next statement of the function
  2. After the function is executed, take out the statements from the top of the stack in turn from the defer stack for execution (Note: follow the stack first in and then out mechanism)
  3. When defer puts the statement on the stack, it will also copy the relevant values into the stack at the same time
func sum(n int,m int){

	defer fmt.Println("----",n)
	defer fmt.Println("****",m)

	n++
	m++

	fmt.Println("And are:",n+m)
}

func main(){
	sum(1,2)
}

//result

/*
Sum: 5
**** 2
---- 1
*/

Best practices

The main value of defer is that it can release the resources created by the function in time after the function is executed

Analog code:

func test(){
	//Close file resource
	file=openfile(file name)
	defer file.close
	
	//Other codes
}

//***************************

fun test(){
    //Free database resources
    connect=openDatabase()
    defer connect.close()
    
    //Other codes
}
  1. The common practice in golang programming is to execute deferfile.Close()deferconnect.Close() after creating resources, such as opening files, obtaining database links, or locking resources
  2. After defer, you can continue to use to create resources
  3. When the function is completed, the system will take out the statements from the defer stack in turn and close the resources
  4. This mechanism is very simple, and programmers don't have to worry about when to turn off resources

Parameter passing method of function

We have already talked about value types and reference types when explaining the precautions and details of function use. Here we will systematically summarize them, because this is the key and difficult point. Value type parameters are value transfer by default, and reference type parameters are reference transfer by default

Two delivery modes

  1. pass by value
  2. Reference passing

In fact, whether it is value transfer or reference transfer, the copy of the variable is passed to the function. The difference is that the value transfer is the copy of the value, and the reference transfer is the copy of the address. Generally speaking, the address copy efficiency is high, because the amount of data is small, and the value copy determines the size of the copied data. The larger the data, the lower the efficiency

Value type and reference type

  • Value types: basic data types: int series, float series, bool,string, array and struct
  • Reference type: pointer, slice slice, map, pipe chan, interface, etc. are all reference types

Use characteristics of value type and reference type

  1. The default value type is value passing: variables store values directly, and memory is usually allocated in the stack
  2. The default reference type is reference passing: variables store an address, and the space corresponding to this address actually stores data. Memory is usually allocated on the heap. When no variables reference this address, the data space corresponding to this address becomes garbage and is recycled by GC
  3. If you want the variables inside the function to modify the variables outside the function, you can pass in the address &, and operate the variables in the function in the form of pointers. In effect, similar references

Variable scope

  1. Variables declared / defined inside a function are called local variables, and the scope is limited to the inside of the function
  2. Variables declared / defined outside the function are called global variables. The scope is valid in the whole package. If its initial letter is uppercase, the scope is valid in the whole program
  3. If the variable is in a code block, such as for/if, the scope of the variable is in the code block

String common system functions

  1. Counts the length of the string, in bytes len(str)
  2. String traversal, while dealing with Chinese problems R: = [] run (STR)
var str string="hello world,Beijing"
	str2:= []rune(str)
	for i:=0;i<len(str2);i++{
		fmt.Printf("%c ",str2[i])
	}
3. String to integer:n,err:=strconv.Atoi("12")
n,err:=strconv.Atoi("hello")
if err!=nil{
	fmt.Println("Conversion error",err)
}else{
	fmt.Println("The result of conversion is",n)
}
  1. Integer to string str=strconv.Itoa(12345)

  2. String to [] byte: var bytes = []byte("hello go")

  3. [] byte to string: str=string([]byte{97,98,99})

  4. Hexadecimal to hexadecimal: STR = strconv.formatint (123,2) / / 2 - > 8,16

  5. Find whether the substring is in the specified character: strings.Contains("seafood", "foo") / / true

  6. Count the number of specified substrings of a string: strings.Count("ceheese", "e") / / 4

  7. Case insensitive string comparison (= = is case sensitive): fmt.Println(strings.EqualFold("ABC", "ABC") / / true

  8. Returns the index value of the substring at the first occurrence of the string. If not, - 1:strings.Index("NLT_abc", "ABC") / / 4

  9. Returns the index of the last occurrence of the substring in the string. If - 1:strings.LastIndex("gogolang", "go") is not returned

  10. Replace the specified substring with another substring: strings.Replace("gogohello", "go", "go language", n)n can specify how many you want to replace. If n=-1, it means to replace all

  11. According to a specified character, split a string into a string array: strings.Split("Hello, wrap, OK", ")

  12. Convert the letters of the string to case:

    strings.ToLower("Go")//go

    strings.ToUpper("Go")//GO

  13. Remove the spaces on the left and right sides of the string: strings.TrimSpace("tnalonegopherntrn")

  14. Remove the characters specified on the left and right sides of the string: strings.Trim("!hello!", "!") / / ["hello"] / / remove the left and right sides of the string! And "" are removed

  15. Remove the specified characters from the left of the string: strings.TrimLeft("!hello!", "!") / / ["hello"] / / the left! And "" are removed

  16. Remove the specified characters from the right side of the string: strings. Trimlight ("! Hello!", "!") / / ["hello"] / / turn the right side! And "" are removed

  17. Judge whether the string starts with the specified string: strings.hasprefix(“ ftp://192.168.10.1 ”,“ftp”)//true

  18. Judge whether the string ends with the specified string: strings.HasSuffix("NLT_abc.jpg", "ABC") / / false

Time and date correlation function

  1. Time and date related functions need to import the time package
  2. time.Time type, used to represent time
now:=time.Now()
fmt.Printf("now :%v type: %T",now,now)
3. How to get other date information
	fmt.Printf("year=%v\n",now.Year())
	fmt.Printf("month=%v\n",now.Month())  //September
	fmt.Printf("month=%v\n",int(now.Month()))  //9
	fmt.Printf("day=%v\n",now.Day())
	fmt.Printf("Time=%v\n",now.Hour())
	fmt.Printf("branch=%v\n",now.Minute())
	fmt.Printf("second=%v\n",now.Second())
  1. Format date time

    Method 1: use Printf or SPrintf

    fmt.Printf("Current date=%d-%d-%d %d:%d:%d\n",now.Year(),now.Month(),now.Day(),now.Hour(),now.Minute(),now.Second())
    
    
    dateStr:=fmt.Sprintf("Current date=%d-%d-%d %d:%d:%d\n",now.Year(),now.Month(),now.Day(),now.Hour(),now.Minute(),now.Second())
    	
    fmt.Printf("Current date=%v",dateStr)
    

    Method 2: use the time.Format() method to complete

    	fmt.Println(now.Format("2006-01-02 15:04:05"))
    	//2021-09-12 22:08:58
    	fmt.Println(now.Format("2006-01-02"))
    	//2021-09-12
    	fmt.Println(now.Format("15:04:05"))
    	//22:08:58
    

    Description of the above code:

    • The numbers of the string "2006 / 01 / 0215:04:05" are fixed and must be written like this.

    • The string "2006 / 01 / 0215:04:05" can be combined freely, so that the time and date can be returned according to the program requirements

      1. Constant of time
const(
    NanosecondDuration=1//nanosecond 			     Microsecond=1000*Nanosecond / / microseconds 	 Millisecond=1000*Microsecond / / milliseconds Second=1000*Millisecond / / seconds Minute=60*Second / / minutes Hour=60*Minute / / hours
)

Function of constant:

  • In the program, it can be used to obtain the time in the specified time unit, such as 100 milliseconds 100*time.Millisecond

    1. Use a time constant in conjunction with Sleep

      time.Sleep(time.Millisecond * 100)
      
    2. time Unix and Unix nano methods

      • Unix represents t as Unix time, that is, the time (in seconds) from January 1, 1970 UTC to time t.
        Under windows, rand.Seed(time.Now().Unix()) is used as seed, and the random number obtained is random

      • UnixNano represents t as UNIX Time, that is, the Time (in nanoseconds) from January 1, 1970 UTC to Time t. If the UNIX Time in nanoseconds exceeds the range that int64 can represent, the result is undefined. Note that this means that if the UnixNano method is called with a Time zero value, the result is undefined.
        Under windows, rand.Seed(time.Now().UnixNano()) is used as the seed, and the random number obtained is not random

    3. Execution time of a program

start:=time.Now().Unix()
test()
end:=time.Now().Unix()
fmt.Printf("implement test Function takes time%v second\n",end-start)

Built in function

Golang designers provide some functions for programming convenience. These functions can be used directly. We call them Go's built-in functions. file: https://studygolang.com/pkgdoc- >builtin

  1. len: used to find the length, such as string, array, slice, map and channel
  2. new: used to allocate memory, mainly used to allocate value types, such as int, float32,struct... Returns pointers
num:=new(int)
//Num is of type * int, and num is an address
   3. make: It is used to allocate memory. It is mainly used to allocate reference types, such as channel,map,slice

error handling

  1. By default, when a panic occurs, the program exits (crashes)
  2. If we want to: when an error occurs, we can catch the error and process it to ensure that the program can continue to execute. You can also give the administrator a prompt (e-mail, SMS...) after capturing the error
  3. This leads to the error handling mechanism we want to use

explain

  • The Go language pursues simplicity and elegance. Therefore, the Go language does not support the traditional try... catch... finally processing.
  • The processing methods introduced in Go are: defer,panic,recover
  • The usage scenarios of these exceptions can be described simply as follows: a panic exception can be thrown in Go, and then the exception can be caught in defer through recover, and then handled normally
func test(){
	defer func() {
		//The recover built-in function can catch exceptions
		err:=recover()
		if err!=nil{ //Description an error was caught
			fmt.Println("The error is:",err)
		}
	}()

	num1:=10
	num2:=0
	res:=num1/num2
	fmt.Println("res=",res)
}

func main(){
	test()
}

//The error is: runtime error: integer divide by zero

benefit

After error handling, the program will not hang up easily. If you add an early warning code, you can make the program more robust

Custom error

The Go program also supports custom errors, using errors.New and panic built-in functions

  1. errors.New("error description") will return a value of error type, indicating an error
  2. The panic built-in function receives a value of interface {} type (that is, any value) as a parameter. It can receive a variable of error type, output an error message, and exit the program

Case:

func readConf(name string)(err error){
	if name=="config.ini"{
		return nil
	}else {
		return errors.New("Error reading file")
	}
}

func test(){
	err:=readConf("conf")
	if err!=nil{
		panic(err)
	}
}

func main(){
	test()
}

array

definition

var array name [array size] data type

var a [5] int

Initial value a [0] = 1, a [1] = 30

var arr [10] float64
arr[0]=1
arr[1]=2
..
  1. The address of the array can be obtained by the array name &arr
  2. The address of the first element of the array is the first address of the array
  3. The address interval of each element of the array is determined according to the type of the array, such as Int64 - > 8int32 - > 4

Initialize array

var numArr01 [3]int = [3]int{1,2,3}
var numArr02 = [3]int{5,6,7}
var numArr03=[...]int{8,9,10}   //[...] is the prescribed writing
var numArr04=[...]int{1:800,0:900,2:999}
strarr05:=[...]string{1:"tom",0:"jack",2:"mary"}

Array traversal

  1. Ordinary for loop traversal
  2. For range traversal
for index,value:=range array01{
    ...
}

/*
index Is an array subscript. If you don't want to use it, use it_
value Is the value of the subscript position
 They are all local variables visible inside the for loop
index And value are not fixed names and can be defined by themselves
*/

heroes :=[...]string{"Song Jiang","Wu Yong","Lu Junyi"}

for i,v:=range heroes{
    fmt.Printf("i=%v v=%v\n",i,v)
    fmt.Printf("heroes[%d]=%v",o,heroes[i])
}

for _,v:=range heroes{
    fmt.Printf("The value of the element is:%v",v)
}

matters needing attention

  1. Array is a combination of multiple data of the same type. Once an array is declared / defined, its length is fixed and cannot change dynamically
  2. var arr[]int at this time, arr is a slice slice, which is specially explained later
  3. The elements in the array can be any data type, including value type and reference type, but they cannot be mixed
  4. After the array is created, if there is no assignment, there is a default value (zero value)
  5. Steps to use an array 1. Declare an array and open up space 2. Assign values to each element of the array (default zero value) 3. Use an array
  6. The subscript of the array starts at 0
  7. The array subscript must be used within the specified range, otherwise panic is reported: the array is out of range, for example, var arr[5]int, the valid subscript is 0-4
  8. Go's array is of value type. By default, it is value transfer, so it will copy values. Arrays will not affect each other
  9. If you want to modify the original array in other functions, you can use reference passing (pointer mode)
func test(arr *[3]int){
    (*arr)[0]=New value
}
   10. The length is a part of the array type. The length of the array needs to be considered when passing function parameters

case

Create an array of 26 elements of byte type and place 'A' - 'Z' respectively. Use the for loop to access all elements and print them. Tip: character data operation 'A' + 1 - > 'B'

var mychars [26]byte
for i:=0;i<26;i++{
	mychars[i]='A'+byte(i)  //Note that i is converted to int
}

Two dimensional array

Syntax: var array name [size] [size] type

For example: var arr [2] [3] int, and then assign value

Memory

Two dimensional array memory, see how many lines, each line has a continuous memory

Initialize array

Declaration: var array name [size] [size] type = [size] [size] type {initial value...}, {initial value...}}

Assignment (with default value, such as 0 for int type)

var arr[2][3]=[2][3]int{{0,1,2},{3,4,5}}

Note: there are also four ways to write two-dimensional arrays when declaring / defining them [similar to one-dimensional arrays]

var array name [size] [size] type = [size] [size] type {initial value...}, {initial value...}}

var array name [size] [size] type = [...] [size] type {initial value...}, {initial value...}}

var array name = [size] [size] type {initial value...}, {initial value...}}

var array name = [...] [size] type {initial value...}, {initial value...}}

ergodic

Mode 1:

Normal for loop

Mode 2:

​ for-range

for i,v1:=range arr{
	for j,v2:range v1{
		fmt.Printf("arr[%v][%v]=%v",i,j,v2)
	}
}

section

  1. Slice is slice in English

  2. A slice is a reference to an array, so a slice is a reference type. When passing, it follows the mechanism of reference passing

  3. The use of slices is similar to that of arrays. Traversing slices, accessing the elements of slices and finding the slice length len(slice) are the same

  4. The length of slices can be changed, so slices are an array that can be changed dynamically

  5. Basic syntax of slice definition:

    Var slice name [] type, for example: var a []int

func main(){
	var numArr04 = [...]int{0:800,1:900,2:999,3:555}
	slice:=numArr04[1:3]  //The subscript includes 1 but does not include 3
	fmt.Println("slice=",slice)
	fmt.Println("slice=",len(slice))  //2 length
	fmt.Println("slice=",cap(slice)) //3 slice capacity
}

cap interpretation

array = []int{1,2,3,4,5,6,7,8,9}

// Take from the array, the left pointer index is 0, the right pointer is 5, and the slice is cut from the array,
// Moreover, the cap function only calculates the number from the left pointer to the last value of the original array
slice = array[0:5]  // slice ==> {1, 2, 3, 4, 5}
cap(slice) // ==9, because the left pointer index is 0, there are 9 numbers to the end, and the cap is 9

slice = slice[2:] // slice ==> {3, 4, 5}
cap(slice) // ==7 the left pointer is offset by 2 steps, so the cap is 9-2 = 7

Memory

The memory storage in the slice is three blocks. The first block is the array address. The position pointed to by the address stores the array elements. The second block is the length len and the third block is the capacity cap

  1. slice is indeed a reference type

  2. slice is actually a data structure (struct structure) from the bottom

    type slice struct{

    ​ ptr *[2] int

    ​ len int

    ​ cap int

    }

use

Mode 1:

Define a slice, and then let the slice refer to an array that has been created. For example, the previous case is like this

Mode 2:

Create slices with make

Basic syntax: var slice name [] type = make([]type,len,[cap])

Parameter Description: Type: is the data type len: size cap: Specifies the slice capacity. Optional. If you have allocated cap, cap > = len is required

var slice[]float64=make([]float64,5,10)
slice[1]=10
slice[3]=10
  1. Creating slices by making lets you specify the size and capacity of the slices
  2. If no value is assigned to each element of the slice, the default value [int, float = > 0, string = > "" bool = > false] will be used
  3. The array corresponding to the slice created by make is maintained by the bottom layer of make and is invisible to the outside, that is, each element can only be accessed through slice

Mode 3:

Define a slice and directly specify a specific array. The principle is similar to make

var strSlice[]string=[]string{"tom","jack","mary"}

ergodic

There are two ways to traverse slices, just like arrays

Mode 1:

Ordinary for loop traversal

Mode 2:

​ for-range

details

  1. During slice initialization, var slice=arr[startIndex:endIndex]

    Note: get the element with index endIndex (excluding arr[endIndex]) from the ARR array with index startIndex

  2. When the slice is initialized, it still cannot cross the boundary. The range is between [0-len(arr)], but it can grow dynamically

    var slice=arr[0:end] can be abbreviated as var slice=arr[:end]

    var slice=arr[start:len(arr)] can be abbreviated as: var slice=arr[start:]

    var slice=arr[0:len(arr)] can be abbreviated as: var slice=arr [:]

  3. cap is a built-in function used to count the capacity of slices, that is, the maximum number of elements that can be stored

  4. After the slice is defined, it cannot be used because it is empty and needs to be referenced to an array or make a space for the slice to use

  5. Slicing can continue slicing

  6. Using the append built-in function, you can dynamically append slices

var slice[]int=[]int{100,200,300}

slice=append(slice,400,500)  //Add

slice=append(slice,slice)  //Add what you already have to the back

Underlying principle analysis of slice append operation:

The essence of slice append operation is to expand the array. The bottom layer of go will create a new array newArr (size after installation and expansion). Copy the elements originally contained in slice to the new array newArrslice and re reference to newArr. Note that newArr is maintained at the bottom layer and cannot be seen by programmers

7. Slice copy operation copy The built-in function completes the copy
copy(slice1,slice2) //Copy slice 2 onto slice 1
  • The data type of the copy(para1,para2) parameter is slice

  • slice1 and slice2 data spaces are independent and do not affect each other

    1. Slice is a reference type, so when passing, it follows the reference passing mechanism
var numArr04 = [...]int{800,900,999,555}
	slice:=numArr04[:]
	fmt.Println("slice=",slice)//[800 900 999 555]
	test(slice)
	fmt.Println("slice=",slice)//[100 900 999 555]
   9. The following code is correct, output 800
var numArr04 = []int{800,900,999,555}
	var slice=make([]int,1)
	copy(slice,numArr04)
	fmt.Println("slice=",slice)  //800

string and slice

  1. The bottom layer of string is a byte array, so string can also be sliced
  2. string has two blocks in memory. The first block is an address pointing to the array element, and the second block is the length
  3. String is immutable, that is, the string cannot be modified by str[0]='z '
  4. If you need to modify a string, you can first convert string - > [] byte / or [] run - > Modify - > rewrite to string

map

map is a key value data structure, also known as a field or associative array. Similar to the collection of other programming languages, it is often used in programming

grammar

var map variable name map[keytype] valuetype

type

  1. What type of key can it be?

The key of map in golang can be of many types, such as bool, number, string, pointer and channel. It can also contain only the interfaces, structures and arrays of the previous types. Generally, the key is int and string. Note: slice, map and function cannot be judged by = =

2. valuetype What type can it be

The type of valuetype is basically the same as that of key. I won't repeat it here. It is usually: number (integer, floating point number), string, map and struct

give an example

var a map[string]string

var a map[string]int

var a map[int]string

var a map[string]map[string]string

The declaration will not allocate memory. make is required for initialization. It can be assigned and used only after memory is allocated

var a map[string]string
	a=make(map[string]string,10)

	a["first"]="Zhang San"
	a["second"]="Li Si"
	a["third"]="Wang Wu"

	fmt.Println("a=",a)

	fmt.Println("first=",a["first"])

//a= map[first: Zhang San second: Li Si third: Wang Wu]
//first = Zhang San

explain:

  1. make a map before using it
  2. The key of map cannot be repeated. If it is repeated, the last key value shall prevail
  3. The value of a map can be the same
  4. The key value of map is unordered
  5. Number of make built-in functions

use

Mode 1:

Previous examples

Mode 2:

The previous example directly a:=make(map[string]string,10)

Mode 3:

a := map[string]string{
		"first":"Zhang San",
		"second":"Li Si",
		"third":"Wang Wu",
	}

	a["fuoth"]="Liu Liu"


	fmt.Println("a=",a)  
//a= map[first: Zhang San fuoth: Liu Liu second: Li Si third: Wang Wu]

	fmt.Println("first=",a["first"])  //first = Zhang San

Small case:

Demonstrate a case where the value of key value is a map. For example, we need to store student information. Each student has name, sex and address information

studentMap := make(map[string]map[string]string)

	studentMap["stu01"]=make(map[string]string)
	studentMap["stu01"]["name"]="tom"
	studentMap["stu01"]["sex"]="male"
	studentMap["stu01"]["address"]="Shandong"

	studentMap["stu02"]=make(map[string]string)
	studentMap["stu02"]["name"]="mary"
	studentMap["stu02"]["sex"]="female"
	studentMap["stu02"]["address"]="Beijing"

	fmt.Println("stu01=",studentMap["stu01"])
	fmt.Println("stu02=",studentMap["stu02"])
	fmt.Println("stu02 sex=",studentMap["stu02"]["sex"])


//stu01= map[address: Shandong name:tom sex: male]
//stu02= map[address: Beijing name:mary sex: female]
//stu02 sex = female

map addition, deletion, modification and query

  1. Map addition and update: map ["key"] = value

    //If the key does not exist, it is added. If the key exists, it is modified.

  2. Map delete: Description: delete(map, "key"), delete is a built-in function. If the key exists, the key value will be deleted. If the key does not exist, no operation will be performed, but no error will be reported

    be careful

    If we want to delete all the keys in a map without a special method, we can traverse the keys and delete them one by one, or map=make(...) and make a new one, so that the original one becomes garbage and is recycled by gc

  3. map lookup:

val,ok:=a["first"]
if ok{
    fmt.Println("yes first key Value is%v",val)
}else{
    fmt.Println("No, first key")
}

Note: if "first" exists in a this map, find Res will return true; otherwise, it will return false

map traversal

The above example

studentMap := make(map[string]map[string]string)

	studentMap["stu01"]=make(map[string]string)
	studentMap["stu01"]["name"]="tom"
	studentMap["stu01"]["sex"]="male"
	studentMap["stu01"]["address"]="Shandong"

	studentMap["stu02"]=make(map[string]string)
	studentMap["stu02"]["name"]="mary"
	studentMap["stu02"]["sex"]="female"
	studentMap["stu02"]["address"]="Beijing"

	for i,v1:=range studentMap{
		fmt.Println(i)
		for j,v2:=range v1{
			fmt.Println(j,v2)
		}
	}

map slice

If the data type of the slice is map, we call it slice of map. In this way, the number of maps can change dynamically

case

Requirement: use a map to record monster's information name and age, that is, a monster corresponds to a map, and the number of monsters can be dynamically increased = > map slice

var monsters []map[string]string
	monsters=make([]map[string]string,2)
	if monsters[0]==nil{
		monsters[0]=make(map[string]string,2)
		monsters[0]["name"]="aaaa"
		monsters[0]["age"]="10"
	}

	if monsters[1]==nil{
		monsters[1]=make(map[string]string,2)
		monsters[1]["name"]="bbbb"
		monsters[1]["age"]="20"
	}

	fmt.Println(monsters[0])  //map[age:10 name:aaaa]
	fmt.Println(monsters[1])  //map[age:20 name:bbbb]
	fmt.Println(monsters[0]["age"])  //10

	//First create a new monster and then append
	newmonster:=map[string]string{
		"name":"cccc",
		"age":"30",
	}
	monsters=append(monsters,newmonster)
	fmt.Println(monsters[2])  //map[age:20 name:bbbb]

map sorting

  1. There is no special method in golang to sort map key s
  2. The map in golang is unordered by default. Note that it is not stored in the order of addition. You may get different output each time you traverse
  3. The sorting of map s in golang is to sort the keys first, and then traverse the output according to the key value
map1:=make(map[int]int,5)
	map1[0]=1
	map1[2]=3
	map1[1]=5
	map1[4]=10
	map1[3]=20
	fmt.Println(map1) //map[0:1 1:5 2:3 3:20 4:10]

	//First put the key of the map into the keys, then sort the key, and finally traverse the key to get the value according to map1[key]
	var keys[]int
	for i,_:=range map1{
		keys=append(keys,i)
	}
	fmt.Println(keys) //[3 0 2 1 4]
	sort.Ints(keys)
	fmt.Println(keys) //[0 1 2 3 4]
	for _,k:=range keys{
		fmt.Printf("map[%v]=%v ",k,map1[k]) 
      //map[0]=1 map[1]=5 map[2]=3 map[3]=20 map[4]=10
	}

details

  1. Map is a reference type. It follows the mechanism of reference type passing. After a function receives a map, it will directly modify the original map
  2. After the capacity of the map is reached, adding elements to the map will automatically expand the capacity without panic, that is, the map can dynamically grow key value pairs
  3. The value of map often uses struct type, which is more suitable for managing complex data (better than the previous value is a map). For example, value is the Student structure

object-oriented programming

  1. Golang also supports object-oriented programming (OOP), but it is different from traditional object-oriented programming. It is not a pure object-oriented language. Therefore, it is accurate to say that golang supports object-oriented programming
  2. Golang does not have classes. The structure of Go language has the same status as the classes of other programming languages. You can understand that golang implements OOP features based on struct
  3. Golang object-oriented programming is very concise, removing the inheritance, method overloading, constructor and destructor, hidden this pointer and so on of the traditional OOP language
  4. Golang still has the characteristics of inheritance, encapsulation and polymorphism of object-oriented programming, but the implementation method is different from other OOP languages. For example, inheritance: golang does not have the extends keyword, and inheritance is realized through anonymous fields
  5. Golang object-oriented (OOP) is very elegant. OOP itself is a part of the language type system. It is associated through the interface. It has low coupling and is very flexible. This feature will be fully realized later. In other words, interface oriented programming is a very important feature in golang

structural morphology

introduction

type Cat struct {
	name string
	age int
	color string
}

func main(){

	var cat1 Cat
	cat1.name="Meow meow"
	cat1.age=12
	cat1.color="gules"

	var cat2 Cat
	cat2.name="Tiger tiger"
	cat2.age=20
	cat2.color="blue"

	fmt.Println(cat1) //{meow 12 red}
	fmt.Println(cat2) //{tiger tiger 20 blue}
}

Fields / properties

  1. From the perspective of concept or nomenclature: structure field = attribute = field (that is, it is called field uniformly in teaching)

  2. A field is an integral part of a structure. It is generally a basic data type, an array, or a reference type. For example, the name string of the cat structure we defined earlier is an attribute

  3. The syntax of field declaration is the same as that of variable. Example: field name field type

  4. The type of field can be: basic type, array or reference type

  5. After creating a structure variable, if no value is assigned to the field, it corresponds to a zero value (default value)

    The zero values of pointer, slice, and map are nil, that is, no space has been allocated

  6. The fields of different structure variables are independent and do not affect each other. The change of one structure variable field does not affect the other. The structure is a value type

Create structure variables and access structure fields

Mode 1:

Directly declare the previous example

Mode 2:

cat3:=Cat{"Mimi",25,"violet"}
fmt.Println(cat3) //{Mimi 25 purple}

Mode 3:

var cat4 *Cat=new(Cat)
	//Because cat4 is a pointer, it needs to be dereferenced. However, the go Creator will operate at the bottom for convenience, so dereferencing has the same effect as dereferencing
	(*cat4).age=30
	cat4.color="blue"
	(*cat4).name="sound of gurgling and water flowing"
	fmt.Println(*cat4) //{Hua Hua 30 blue}

Mode 4:

var cat5 *Cat=&Cat{}
	//Same as mode 3
	cat5.name="Sisi"
	cat5.age=35
	(*cat5).color="yellow"
	fmt.Println(*cat5) //{West 35 yellow}

explain:

  1. The third and fourth methods return structure pointers
  2. The standard way for a structure pointer to access a field should be: (* structure pointer). Field name
  3. However, go makes a simplification and also supports structure pointer and field name, such as person.Name = "tom". It is more in line with the habits of programmers. The bottom layer of go compiler converts person.Name (* person).Name)
  4. The operation priority of * is higher than *

details

  1. All fields of the structure are contiguous in memory
  2. A structure is a user-defined type. It needs exactly the same fields (name, number and type) when converting with other types
  3. The structure is redefined by type (equivalent to taking an alias). Golang thinks it is a new data type, but it can be forcibly converted to each other
  4. A tag can be written on each field of struct, which can be obtained through the reflection mechanism. The common use scenarios are serialization and deserialization (introduced in the reflection section)

method

In some cases, we need to declare (define) methods. For example, Cat structure: in addition to some fields (age, name...), Person structure also has some behaviors, such as speaking, running..., and doing arithmetic problems through learning. At this time, we need to use methods to complete it

The methods in Golang act on the specified data type (that is, bind to the specified data type). Therefore, custom types can have methods, not just struct s

Declarations and calls

func (c Cat) test(){
	fmt.Println("test...",c.name)
}

cat5.test() //West... West
cat1.test() //test... Meow
  1. Func (A) test() {} indicates that the A structure has A method named test
  2. (a) the test method is bound to type A
  3. test method and Cat type binding
  4. The test method can only be called through variables of Cat type, not directly, nor can it be called with variables of other types
  5. func(c Cat) test() {}... p indicates which Cat variable is called, and this c is its copy, which is very similar to the function parameter passing
  6. The name c is specified by the programmer and is not fixed. For example, it can be modified to cat

Call and pass parameter mechanism

The mechanism of method calling and parameter passing is basically the same as that of a function. The difference is that when a method is called, the variable calling the method will also be passed to the method as an argument

Explain

  1. When a method is called through a variable, its calling mechanism is the same as that of a function
  2. In different places, when a variable calls a method, the variable itself will also be passed to the method as a parameter (if the variable is a value type, copy the value; if the variable is a reference type, copy the value)

Method declaration (definition)

func(recevier type) methodName(Parameter list)(Return value list){

	Method body

	return Return value

}
  1. Parameter list: indicates method input
  2. receviertype: indicates that the method is bound to the type, or the method acts on the type
  3. receivertype:type can be a structure or other user-defined types
  4. receiver: is a variable (instance) of type, such as a variable (instance) of Person structure
  5. Return value list: indicates the returned value, which can be multiple
  6. Method body: represents a code block to implement a function
  7. The return statement is not required

details

  1. Structure type is a value type. In method invocation, the value type transfer mechanism is followed, which is the value copy transfer mode
  2. If a programmer wants to modify the value of a structure variable in a method, it can be handled by a structure pointer
  3. The methods in Golang act on the specified data type (i.e. bind to the specified data type). Therefore, custom types can have methods, not just struct s, such as int,float32, etc
  4. The rules of access scope control of methods are the same as those of functions. The first letter of the method name is lowercase and can only be accessed in this package. The first letter of the method is uppercase and can be accessed in this package and other packages
  5. If a type implements the String() method, fmt.Println will call the String() of this variable for output by default

Differences between methods and functions

  1. The calling method is different
  2. For ordinary functions, when the receiver is of value type, the data of pointer type cannot be passed directly, and vice versa
  3. For methods (such as struct methods), when the receiver is a value type, you can directly call the method with a pointer type variable, and vice versa
    • Regardless of the call form, the real decision is whether to copy the value or address, depending on which type the method is bound to
    • If it is a and value type, such as (p Person), it is a value copy; if it is a and pointer type, such as (p*Person), it is an address copy

Factory mode

Tags: Go Visual Studio Code

Posted on Thu, 16 Sep 2021 17:43:53 -0400 by Michael_zz