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:
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) }
Define an interface in which the required interfaces are designed, and there can be multiple (attack(), attack() 1..)
Any class that implements this interface can be assigned to this interface to realize polymorphism
There is no need for inheritance between multiple classes
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 { ; } }
- When the number of reads and writes of the pipeline is inconsistent
- If the block is in the main go process, the program will crash
- 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!") }