Golang basic syntax supplement

1, Basic grammar supplement

1. switch

package main

import (
    "fmt"
    "os"
)

//Input parameters from the command and process them in switch

func main() {
    //C: argc , **argv
    //Go: OS. Args = = > command input can be obtained directly. It is a string slice [] string
    cmds := os.Args

    //OS. Args [0] = = > program name
    //OS. Args [1] = = > the first parameter, and so on
    for key, cmd := range cmds {
        fmt.Println("key:", key, ", cmd:", cmd, ", cmds len:", len(cmds))
    }

    if len(cmds) < 2 {
        fmt.Println("Please input the parameters correctly!")
        return
    }

    switch cmds[1] {
    case "hello":
        fmt.Println("hello")
        //go's switch is added with break by default, and manual processing is not required
        //If you want to penetrate downward, you need to add the keyword: fallthrough
        fallthrough
    case "world":
        fmt.Println("world")
    default:
        fmt.Println("default called!")
    }
}

2. Label

package main

import "fmt"

func main() {
    //Label LABEL1
    //Goto label = = = > the next time you enter the loop, i will not save the previous state. Start calculation from 0 and start again
    //Continue label1 = = = > continue will jump to the specified location, but the previous status will be recorded, and i will change to 1
    //Break label1 = = > directly jump out of the loop at the specified position

    //The label name is custom, followed by a colon
LABEL121:
    for i := 0; i < 5; i++ {
        for j := 0; j < 5; j++ {
            if j == 3 {
                //goto LABEL1
                //continue LABEL1
                break LABEL121
                //break
            }

            fmt.Println("i:", i, ",j:", j)
        }
    }

    fmt.Println("over!")
}

3. Enumerate const+iota

package main

import "fmt"

//There is no enumeration type in go language, but we can use const + iota (constant accumulator) for simulation
//Simulate a week's enumeration
const (
    MONDAY    = iota       //0
    TUESDAY   = iota       //1
    WEDNESDAY = iota       //2
    THURSDAY               //3 = = > no assignment. The default is the same as the previous line. Iota = = > 3
    FRIDAY                 //4
    SATURDAY               //5
    SUNDAY                 //6
    M, N      = iota, iota //const belongs to the pre compilation period assignment, so it is not necessary to automatically derive: =
)

const (
    JANU = iota + 1 //1
    FER             //2
    MAR             //3
    APRI            //4
)

//1. iota is a constant group counter
//2.iota starts from 0 and increments by 1 for each line break
//3. The constant group has a feature. If no value is assigned, the default is the same as the expression in the previous line
//4. If two iotas appear in the same row, the values of the two iotas are the same
//5. The iota of each constant group is independent. If const iota is encountered, it will be reset

func main() {

    fmt.Println("Print week:")
    fmt.Println(MONDAY)
    fmt.Println(TUESDAY)
    fmt.Println(WEDNESDAY)
    fmt.Println(THURSDAY)
    fmt.Println(FRIDAY)
    fmt.Println("M:", M, ",N:", N)

    fmt.Println("Print month:")
    fmt.Println(JANU) //1
    fmt.Println(FER)  //2
    fmt.Println(MAR)  //3

    //var number int
    //var name string
    //var flag bool
    //
    //
    ////You can use variable groups to uniformly define variables
    //var (
    //    number int
    //    name string
    //    flag bool
    //)

}

Configure git shell in Golan and display Chinese:

www.bbsmax.com/A/n2d9YvN6dD/

My installation path D:\Program Files (x86)\Tools\Git\Git\etc)lower bash.bashrc file

export LANG="zh_CN.UTF-8"
export LC_ALL="zh_CN.UTF-8"

git terminal display settings:

4. Structure

In the go language, structs are used to simulate classes

package main

import "fmt"

//In c language, we can use typedef int Myint
type MyInt int //type is equivalent to typdef

//C:
//struct Person {
//
//}

//go language constructs are handled using type + struct
type Student struct {
    name   string
    age    int
    gender string
    score  float64
}

func main() {
    t1 := struct {
        a int
    }{
        a : 100
    }

    fmt.Println(t1)

    var i, j MyInt
    i, j = 10, 20

    fmt.Println("i+j:", i+j)

    //Create variables and assign values
    lily := Student{
        name:   "Lily",
        age:    20,
        gender: "girl student",
        //Score: 80, / / the last element must be followed by a comma. If not, it must be on the same line as}
        //}
        score: 80} //The last element must be followed by a comma. If not, it must be on the same line as}

    //Use structure fields
    fmt.Println("lily:", lily.name, lily.age, lily.gender, lily.score)

    //Structure has no - > operation
    s1 := &lily
    fmt.Println("lily Use pointer s1.name Print:", s1.name, s1.age, s1.gender, s1.score)
    fmt.Println("lily Use pointer(*s1).name Print:", (*s1).name, s1.age, s1.gender, s1.score)

    //When assigning a value to a structure during definition, if each field is assigned, the name of the field can be omitted
    //If only local variables are assigned, the variable name must be specified explicitly
    Duke := Student{
        name: "Duke",
        age:  28,
        //"Boys",
        // 99,
    }
    Duke.gender = "schoolboy"
    Duke.score = 100

    fmt.Println("Duke:", Duke)
}

5.init function

C language does not have init function. C language usually needs to write init itself, and then calls in constructor.

Go language comes with init function, and each package can contain one or more init functions

package sub

import "fmt"

//0. This init will be called automatically when the package is referenced (import)
//1. The init function has no parameters and no return value. The prototype is fixed as follows
//2. When a package contains multiple inits, the calling order is uncertain (multiple files in the same package can have inits)
//3. The user is not allowed to display the called in init function
//4. Sometimes, when referring to a package, you may only want to use the init function in the package (mysql init to initialize the driver)
//However, you do not want to use other functions in this package. In order to prevent the compiler from reporting errors, you can use_ Form to deal with
//import _ "xxx/xx/sub"
func init() {
    fmt.Println("this is first init() in package sub ==> sub.go")
}

func init() {
    fmt.Println("this is second init() in package sub ==> sub.go ")
}

//In go language, multiple package names are not allowed in the same level directory
func Sub(a, b int) int {
    //Init() = = > display call not allowed
    test4() //Since test4 is under the same package as sub.go, it can be used without the form of sub
    return a - b
}

utils.go

package sub

//package utils / / multiple package names are not allowed

import "fmt"

func init() {
    fmt.Println("this is init in sub utils.go")
}

func test4() {
    fmt.Println("this is test4() in sub/utils!")
}

main.go

package main

import (
    _ "day02/05-init function/sub" //At this time, only the init function in sub will be called, and the compilation will not make an error
    //"fmt"
)

func main() {
    //res := sub.Sub(10, 5)
    //fmt.Println("sub.Sub(20,10) =", res)
}

effect:

Using the init scenario, write init in the configuration file manager to load and parse the configuration file:

configManager {
    //Parse load profile
    //IP, PORT
}

6. Defer

Delay, keyword, can be used to modify statements and functions to ensure that this statement can be executed when the current stack exits

lock.Lock()
a = "hello"
lock.Unlock()   <=== It's often easy to forget to unlock

go language can use defer to solve this problem

{
    lock.Lock()
    defer lock.Unlock()   <=== When the current stack exits (for example, when the function ends)
    a = "hello"
}

{
    f1,_ := file.Open()
    defer f1.Close()
}

example:

package main

import (
    "fmt"
    "os"
)

func main() {
    //1. Delay, keyword, can be used to modify statements and functions to ensure that this statement can be executed when the current stack exits
    //2. It is generally used to clean up resources
    //3. Unlock and close files
    //4. defer is called multiple times in the same function. During execution, it is similar to the stack mechanism: in and out successively

    filename := "01-switch.go"
    readFile(filename)
}

func readFile(filename string) {
    //func Open(name string) (*File, error) {
    //1. go language generally returns the error code as the last parameter
    //2. err generally, nil means no error and successful execution. Non nil means failed execution
    f1, err := os.Open(filename)

    //Anonymous function, without name, belongs to one-time logic = = > lamada expression
    defer func(a int) {
        fmt.Println("Ready to close file, code:", a)
        _ = f1.Close()
    }(100) //Create an anonymous function and call

    if err != nil {
        fmt.Println("os.Open(\"01-switch.go\") ==> fail to open file, err:", err)
        return
    }

    defer fmt.Println("0000000")
    defer fmt.Println("1111111")
    defer fmt.Println("2222222")

    buf := make([]byte, 1024)  //byte ==> char ==> uint8
    //func (f *File) Read(b []byte) (n int, err error) {
    n, _ := f1.Read(buf)
    fmt.Println("Read the actual length of the file:", n)
    fmt.Println("Read file contents:", string(buf))  ==> Type conversion

}

2, Class related operations

go language supports class operations, but there is no class keyword. Use struct to simulate classes

1. Encapsulation binding method

package main

import "fmt"

//Person class, binding method: Eat, Run, Laugh, member
//public,private
/*
class Person {
public :
    string name
    int age

public :
    Eat() {
        xxx
    }
}

*/

//Any type of type can bind methods
type MyInt1 int

func (mi *MyInt1) printMyInt() {
    fmt.Println("MyInt value is:", *mi)
}

type Person struct {
    //Member properties:
    name   string
    age    int
    gender string
    score  float64
}
/*
Person:::Eat() {

}
*/

//Binding methods outside a class
func (this *Person) Eat() {
    //fmt.Println("Person is eating")
    //Class, you can use your own members
    //fmt.Println(this.name + " is eating!")
    this.name = "Duke"
}

func (this Person) Eat2() {
    fmt.Println("Person is eating")
    //Class, you can use your own members
    this.name = "Duke"
}

func main() {
    lily := Person{
        name:   "Lily",
        age:    30,
        gender: "girl student",
        score:  10,
    }

    lily1 := lily

    fmt.Println("Eat,use p *Person,modify name Value of ...")
    fmt.Println("Before modification lily:", lily) //lily
    lily.Eat()
    fmt.Println("After modification lily:", lily) //Duke

    fmt.Println("Eat2,use p Person,But not a pointer ...")
    fmt.Println("Before modification lily:", lily1) //lily
    lily1.Eat2()
    fmt.Println("After modification lily:", lily1) //lily

    var myint1 MyInt1 = 100
    myint1.printMyInt()
}

2. Class inheritance

package main

import "fmt"

type Human struct {
    //Member properties:
    name   string
    age    int
    gender string
}

//Binding methods outside a class
func (this *Human) Eat() {
    fmt.Println("this is :", this.name)
}

//Define a student class to nest a Hum
type Student1 struct {
    hum    Human //Contains variables of Human type, which is the nesting of classes
    score  float64
    school string
}

//Define a teacher to inherit Human
type Teacher struct {
    Human          //Write Huam type directly without field name
    subject string //subject
}

func main() {
    s1 := Student1{
        hum: Human{
            name:   "Lily",
            age:    18,
            gender: "girl student",
        },
        school: "Changping No. 1 middle school",
    }

    fmt.Println("s1.name:", s1.hum.name)
    fmt.Println("s1.school:", s1.school)

    t1 := Teacher{}
    t1.subject = "language"
    t1.name = "Teacher Rong" //The following fields are inherited from Human
    t1.age = 35
    t1.gender = "girl student"

    fmt.Println("t1 :", t1)
    t1.Eat()

    //During inheritance, although we do not define a field name, a default field with the same name will be automatically created
    //This is so that the parent class can still be manipulated in the child class, because the child class and parent class may have fields with the same name
    fmt.Println("t1.Human.name:", t1.Human.name)
}

Access rights

//In the go language, permissions are controlled by the initial size
//1. import = = "if the package names are different, only those beginning with capital letters are public
//2. For members and methods in the class, only those beginning with uppercase can be used in other packages

3. interface

package main

import "fmt"

//In C + +, when implementing the interface, pure virtual functions are used to replace the interface
//In go language, there is a special keyword interface to represent the interface
//interface is not only used to deal with polymorphism, it can accept any data type, which is a bit similar to void

func main() {
    //func Println(a ...interface{}) (n int, err error) {
    fmt.Println("")

    //var i,j,k int
    //Define three interface types
    var i, j, k interface{}
    names := []string{"duke", "lily"}
    i = names
    fmt.Println("i Represents an array of slices:", i)

    age := 20
    j = age
    fmt.Println("j Representative number:", j)

    str := "hello"
    k = str
    fmt.Println("k Representative string:", k)

}

package main

import "fmt"

//In C + +, when implementing the interface, pure virtual functions are used to replace the interface
//In go language, there is a special keyword interface to represent the interface
//interface is not only used to deal with polymorphism, it can accept any data type, which is a bit similar to void

func main() {
    //func Println(a ...interface{}) (n int, err error) {
    fmt.Println("")

    //var i,j,k int
    //Define three interface types
    var i, j, k interface{}
    names := []string{"duke", "lily"}
    i = names
    fmt.Println("i Represents an array of slices:", i)

    age := 20
    j = age
    fmt.Println("j Representative number:", j)

    str := "hello"
    k = str
    fmt.Println("k Representative string:", k)

    //We only know that k is an interface, but we can't clearly know the type of data it represents
    kvalue, ok := k.(int)  //< < = = = = make secondary confirmation of type
    if !ok {
        fmt.Println("k no int")
    } else {
        fmt.Println("k yes int, Value is:", kvalue)
    }

    //The most common scenario: take the interface as a function parameter (similar to print), and use switch to judge the different types of user input
    //Make corresponding logical processing according to different types

    //Create a slice with three interface types
    array := make([]interface{}, 3)
    array[0] = 1
    array[1] = "Hello world"
    array[2] = 3.14

    for _, value := range array {
        //You can get the real data type of the current interface
        switch v := value.(type) {
        case int:
            fmt.Printf("Current type is int, The content is:%d\n", v)
        case string:
            fmt.Printf("Current type is string, The content is: %s\n", v)
        case bool:
            fmt.Printf("Current type is bool, The content is: %v\n", v) //%v can be automatically pushed to the output type
        default:
            fmt.Println("Is not a reasonable data type")
        }
    }
}

4. Polymorphism

Polymorphism in C language requires parent-child inheritance

The polymorphism of go language does not need inheritance, as long as it implements the same interface

package main

import "fmt"

//To realize go polymorphism, you need to implement the defined interface
//When human weapons attack, different levels of bullets have different effects

//Define an interface. Note that the type is interface
type IAttack interface {
    //There can be multiple interface functions, but there can only be function prototypes, not implementations
    Attack()
    //Attack1()
}

//Low grade
type HumanLowLevel struct {
    name  string
    level int
}

func (a *HumanLowLevel) Attack() {
    fmt.Println("I am:", a.name, ",Grade is:", a.level, ", Cause 1000 points of damage")
}

//high-grade
type HumanHighLevel struct {
    name  string
    level int
}

func (a *HumanHighLevel) Attack() {
    fmt.Println("I am:", a.name, ",Grade is:", a.level, ", Cause 5000 points of damage")
}

//Define a polymorphic general interface, pass in different objects and call the same method to achieve different effects
func DoAttack(a IAttack) {
    a.Attack()
}

func main() {
    //var player interface{}
    var player IAttack //Define an interface variable containing Attack

    lowLevel := HumanLowLevel{
        name:  "David",
        level: 1,
    }

    highLevel := HumanHighLevel{
        name:  "David",
        level: 10,
    }

    lowLevel.Attack()
    highLevel.Attack()

    //Assign lowLevel to player, and the interface needs to use pointer type to assign value
    player = &lowLevel
    player.Attack()

    player = &highLevel
    player.Attack()

    fmt.Println("polymorphic......")
    DoAttack(&lowLevel)
    DoAttack(&highLevel)
}

  1. Define an interface in which the required interfaces are designed, and there can be multiple (attack(), attack() 1..)

  2. Any class that implements this interface can be assigned to this interface to realize polymorphism

  3. There is no need for inheritance between multiple classes

  4. If multiple interfaces are defined in the interface, the actual class must implement all interface functions before assignment

3, Concurrent correlation

1. Foundation

Concurrent: the computer listens to songs, reads novels and watches movies at the same time. The cpu is divided according to the time slice and executes the three programs alternately. We can feel that it happens at the same time.

Parallel: multiple CPU s (multiple cores) execute simultaneously

In C language, multithreading (the smallest resource unit of C + +) is used to realize concurrent processes

The go language is not a thread, but a go process = = > goroutine. The go process is natively supported by the go language

Each go process occupies far less system resources than threads. A go process requires about 4K~5K memory resources

A program can start a large number of go programs:

  • Dozens of threads
  • The go process can start hundreds or thousands of programs, and the performance is very good for achieving high concurrency
  • Just add the go keyword before the objective function
package main

import (
    "fmt"
    "time"
)

//This will be used by subprocesses
func display() {
    count := 1
    for {
        fmt.Println("=============> This is the son go Course:", count)
        count++
        time.Sleep(1 * time.Second)
    }
}

func main() {
    //Promoter go process
    //go display()
    go func() {
        count := 1
        for {
            fmt.Println("=============> This is the son go Course:", count)
            count++
            time.Sleep(1 * time.Second)
        }
    }()

    //Main go process
    count := 1
    for {
        fmt.Println("This is the Lord go Course:", count)
        count++
        time.Sleep(1 * time.Second)
    }
}

When multiple word go programs are started, they will compete for cpu resources

package main

import (
    "fmt"
    "time"
)

//This will be used by subprocesses
func display(num int) {
    count := 1
    for {
        fmt.Println("=============> This is the son go Course:", num, "current count value:", count)
        count++
        //time.Sleep(1 * time.Second)
    }
}

func main() {
    //Promoter go process
    for i := 0; i < 3; i++ {
        go display(i)
    }

    //go func() {
    //    count := 1
    //    for {
    //        FMT. Println ("================= > this is a sub go procedure:", count)
    //        count++
    //        time.Sleep(1 * time.Second)
    //    }
    //}()

    //Main go process
    count := 1
    for {
        fmt.Println("This is the Lord go Course:", count)
        count++
        time.Sleep(1 * time.Second)
    }
}

2. Early exit

package main

import (
    "fmt"
    "runtime"
    "time"
)

//Return = = > returns the current function
//Exit = = > exit the current process
//Goexit = = > exit the current go process in advance

func main() {
    go func() {
        go func() {
            func() {
                fmt.Println("This is the son go Function inside the program!")
                //return / / this is the function that returns the current value
                //os.Exit(-1) / / exit the process
                runtime.Goexit() //Exit the current go process
            }()

            fmt.Println("son go End of process!") //Can this sentence be printed? 2: do not print
            fmt.Println("go 2222222222 ")

        }()
        time.Sleep(2 * time.Second)
        fmt.Println("go 111111111111111")
    }()

    fmt.Println("This is the Lord go Course!")
    time.Sleep(3 * time.Second)
    fmt.Println("OVER!")
}

3. Non buffered channel

package main

import (
    "fmt"
    "time"
)

func main() {
    //sync.RWMutex{}
    //When it comes to multi go processes, c language uses mutual exclusion and locking to keep resources synchronized and avoid resource competition
    //The go language also supports this method, but a better solution for the go language is to use pipes and channel s
    //Using the channel does not require us to add and unlock
    //A writes data to the channel, B reads data from the pipeline, and go automatically helps us synchronize the data

    //Create pipe: create a pipe with numbers = = > Channel
    //Strchan: = make (Chan string) / / pipeline for string loading

    //make(map[int]string, 10)
    //When installing a digital pipeline, you must make it, the same as map, otherwise it is nil
    //This is an unbuffered pipe
    //numChan := make(chan int)

    //Buffered pipe
    numChan := make(chan int, 10)

    //Create two go processes. The father writes data and the son reads data
    go func() {
        for i := 0; i < 50; i++ {
            data := <-numChan
            fmt.Println("son go Process 1 read data  ===> data:", data)
        }
    }()

    go func() {
        for i := 0; i < 20; i++ {
            //Write data to pipeline
            numChan <- i
            fmt.Println("son go Process 2 write data:", i)
            //time.Sleep(1 * time.Second)
        }
    }()

    for i := 20; i < 50; i++ {
        //Write data to pipeline
        numChan <- i
        fmt.Println("======> This is the Lord go Course, Write data:", i)
        //time.Sleep(1 * time.Second)
    }

    time.Sleep(5 * time.Second)
}

4. Pipeline with buffer zone

package main

import (
    "fmt"
    "time"
)

func main() {
    //numsChan := make(chan int, 10)
    //1. When the buffer is full, the write is blocked. When it is read, the write is resumed
    //2. When the buffer is read, the read is blocked
    //3. If the pipeline does not use make to allocate space, the pipeline defaults to nil, and reading and writing will be blocked
    //4. For a pipeline, the number of reads and writes must be equal

    var names chan string //The default is nil
    names = make(chan string, 10)

    go func() {
        fmt.Println("names:", <-names)
    }()

    names <- "hello" //Since names is nil, write operations will be blocked here
    time.Sleep(1 * time.Second)

    numsChan1 := make(chan int, 10)

    //write
    go func() {
        for i := 0; i < 50; i++ {
            numsChan1 <- i
            fmt.Println("Write data:", i)
        }
    }()

    //Read, when the main program is blocked by the pipeline, the program will lock and crash
    //We are required to keep the same reading and writing times
    func() {
        for i := 0; i < 60; i++ {
            fmt.Println("The main program is ready to read data.....")
            data := <-numsChan1
            fmt.Println("Read data:", data)
        }
    }()

    for {
        ;
    }
}
  1. When the number of reads and writes of the pipeline is inconsistent
    1. If the block is in the main go process, the program will crash
    2. If it is blocked in a child go procedure, a memory leak will occur

5. for range traversal

package main

import "fmt"

func main() {

    numsChan2 := make(chan int, 10)

    //write
    go func() {
        for i := 0; i < 50; i++ {
            numsChan2 <- i
            fmt.Println("Write data:", i)
        }
        fmt.Println("After all the data are written, prepare to close the pipeline!")
        close(numsChan2)
    }()

    //When traversing the pipeline, only one value is returned
    //for range doesn't know whether the pipeline has been written, so it will always wait here
    //On the write side, close the pipeline. When for range traverses the closed pipeline, it will exit
    for v := range numsChan2 {
        fmt.Println("Read data :", v)
    }

    fmt.Println("OVER!")
}

Posted by whitsey on Wed, 24 Nov 2021 04:06:23 -0800