Introduction to Go language
Go is an open source programming language that makes it easy to construct simple, reliable and efficient software.
Go language is designed as a system programming language for huge central servers equipped with Web servers, storage clusters or similar purposes.
For the field of high-performance distributed systems, Go language undoubtedly has higher development efficiency than most other languages. It provides massive parallel support, which is the best for the development of game server.
First Go program:
go installation address: https://golang.google.cn/dl/
Let's write the first program Go (the extension of go language source file is. Go), and the code is as follows:
hello.go file
package main import "fmt" func main() { fmt.Println("Hello, World!") }
To execute the Go language code, you can use the go run command.
$ go run hello.go Hello, World! In addition, we can also use go build Command to generate binaries: $ go build hello.go $ ls hello hello.go $ ./hello Hello, World!
Go language structure
The basic components of Go language are as follows:
- Package declaration
- Introduction package
- function
- variable
- Statement & expression
- notes
package main // Package declaration import "fmt" // Package reference func main() { // Function must contain. It should be noted that {cannot be placed on a single line /* This is my first simple program */ fmt.Println("Hello, World!") }
- When the identifier (including constant, variable, type, function name, structure field, etc.) starts with a capital letter, such as Group1, the object using this form of identifier can be used by the code of the external package (the client program needs to import this package first), which is called export (like public in object-oriented language);
- When identifiers start with lowercase letters, they are not visible outside the package, but they are visible and available inside the whole package (like protected in object-oriented languages).
file structure : Test --helloworld.go myMath --myMath1.go --myMath2.go
// helloworld.go package main import ( "fmt" "./myMath" ) func main(){ fmt.Println("Hello World!") fmt.Println(mathClass.Add(1,1)) fmt.Println(mathClass.Sub(1,1)) }
// myMath1.go package mathClass func Add(x,y int) int { return x + y }
// myMath2.go package mathClass func Sub(x,y int) int { return x - y }
Format string:
fmt.Sprintf formats the string and assigns it to the new string:
package main import ( "fmt" ) func main() { // %d represents an integer number and% s represents a string var stockcode=123 var enddate="2020-12-31" var url="Code=%d&endDate=%s" var target_url=fmt.Sprintf(url,stockcode,enddate) fmt.Println(target_url) }
Go language variable
The general form of declaring variables is to use the var keyword:
var identifier type You can declare multiple variables at once: var identifier1, identifier2 type intVal := 1 Equal to: var intVal int intVal =1
package main import "fmt" func main() { var a string = "Runoob" // a1 := "Ruoob" fmt.Println(a) var b, c int = 1, 2 fmt.Println(b, c) } //This non declarative format can only appear in the body of a function //g, h := 123, "hello"
- If you use variable a before defining it, you will get a compilation error undefined: a.
- If you declare a local variable but do not use it in the same code block, you will also get a compilation error, a declared but not used.
- Variables declared outside the function are called global variables. Global variables can be used in the whole package or even external packages (after being exported). However, global variables are not allowed to be used after declaration.
Go language constant
The data types in constants can only be Boolean, numeric (integer, floating point and complex) and string.
You can omit the type specifier [type] because the compiler can infer the type of a variable based on its value.
- Explicit type definition: const b string = "abc"
- Implicit type definition: const b = "abc"
Go language operator
/* & And * operator instances */ ptr = &a /* 'ptr' Contains the address of the 'a' variable */ fmt.Printf("a The value of is %d\n", a); fmt.Printf("*ptr by %d\n", *ptr);
Go language loop statement
There are three forms of For loop in Go language, and only one of them uses semicolon.
Like for in C language:
for init; condition; post { } init: Generally, it is an assignment expression, which assigns an initial value to the control variable; condition: Relational expression or logical expression, loop control condition; post: Generally, it is an assignment expression, which increments or decrements the control variable.
Like C's while:
for condition { }
for(;) of and C Same:
for { }
The range format of the for loop can iterate over slice, map, array, string, etc. The format is as follows:
for key, value := range oldMap { newMap[key] = value }
Calculate the sum of numbers from 1 to 10:
package main import "fmt" func main() { sum := 0 for i := 0; i <= 10; i++ { sum += i } fmt.Println(sum) }
The init and post parameters are optional. We can omit them directly, similar to the While statement.
package main import "fmt" func main() { sum := 1 for ; sum <= 10; { sum += sum } fmt.Println(sum) // It can also be written in this way, which is more like the form of While statement for sum <= 10{ sum += sum } fmt.Println(sum) }
Infinite loop: to stop the infinite loop, press ctrl-c in the command window.
package main import "fmt" func main() { sum := 0 for { sum++ // Infinite cycle } fmt.Println(sum) // Unable to output }
For each range loop
The range format of the for loop can iterate over slice, map, array, string, etc. The format is as follows:
for key, value := range oldMap { newMap[key] = value }
package main import "fmt" func main() { strings := []string{"google", "runoob"} for i, s := range strings { fmt.Println(i, s) } numbers := [6]int{1, 2, 3, 5} for i,x:= range numbers { fmt.Printf("The first %d position x Value of = %d\n", i,x) } }
The output results of the above examples are:
0 google 1 runoob Bit 0 x Value of = 1 1st place x Value of = 2 2nd place x Value of = 3 3rd place x Value of = 5 4th place x Value of = 0 5th place x Value of = 0
Go language function
Go language function definition format is as follows:
func function_name( [parameter list] ) [return_types] { Function body }
package main import "fmt" func main() { /* Define local variables */ var a int = 100 var b int = 200 var ret int /* Call the function and return the maximum value */ ret = max(a, b) fmt.Printf( "Is the maximum value : %d\n", ret ) } /* Function returns the maximum value of two numbers */ func max(num1, num2 int) int { /* Define local variables */ var result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
Function returns multiple values
package main import "fmt" func swap(x, y string) (string, string) { return y, x } func main() { a, b := swap("Google", "Runoob") fmt.Println(a, b) }
The execution result of the above example is:
Runoob Google
Language function reference passing value
Reference passing refers to passing the address of the actual parameter to the function when calling the function. Then the modification of the parameter in the function will affect the actual parameter.
The reference passing pointer parameter is passed into the function. The following is the reference passing used by the exchange function swap():
It is allowed to pass a pointer to a function, which only needs to be set as the pointer type on the parameter of the function definition.
package main import "fmt" func main() { /* Define local variables */ var a int = 100 var b int= 200 fmt.Printf("Before the exchange, a Value of : %d\n", a ) fmt.Printf("Before the exchange, b Value of : %d\n", b ) /* Call swap() function * &a Pointer to a, address of a variable * &b Pointer to b, address of b variable */ swap(&a, &b) fmt.Printf("After the exchange, a Value of : %d\n", a ) fmt.Printf("After the exchange, b Value of : %d\n", b ) } func swap(x *int, y *int) { var temp int temp = *x /* Save value on x address */ *x = *y /* Assign y value to x */ *y = temp /* Assign temp value to y */ }
The execution result of the above code is:
Before the exchange, a Value of : 100 Before the exchange, b Value of : 200 After the exchange, a Value of : 200 After the exchange, b Value of : 100
Go language array
The Go language array declaration needs to specify the element type and number of elements. The syntax format is as follows:
var variable_name [SIZE] variable_type
var balance [10] float32 var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
If the length of the array is uncertain, you can use... Instead of the length of the array. The compiler will infer the length of the array according to the number of elements:
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} or balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
If the length of the array is set, we can also initialize elements by specifying subscripts:
// Initializes elements with indexes 1 and 3 balance := [5]float32{1:2.0,3:7.0} 1:2 3:7
Accessing array elements
var salary float32 = balance[9]
package main import "fmt" func main() { var n [10]int /* n Is an array with a length of 10 */ var i,j int /* Initializing elements for array n */ for i = 0; i < 10; i++ { n[i] = i + 100 /* Set element to i + 100 */ } /* Output the value of each array element */ for j = 0; j < 10; j++ { fmt.Printf("Element[%d] = %d\n", j, n[j] ) } }
Go language pointer
What is a pointer?
A pointer variable points to the memory address of a value.
Like variables and constants, you need to declare pointers before using them. The format of pointer declaration is as follows:
var var_name *var-type var-type Is a pointer type, var_name Is the pointer variable name,* The number is used to specify that the variable is used as a pointer. The following are valid pointer declarations: var ip *int /* Pointing integer*/ var fp *float32 /* Point to floating point */
How do I use pointers?
Pointer usage process:
- Define pointer variables.
- Assign values to pointer variables.
- Access the value pointing to the address in the pointer variable.
Add a * sign (prefix) before the pointer type to get the content pointed to by the pointer.
package main import "fmt" func main() { var a int= 20 /* Declare actual variables */ var ip *int /* Declare pointer variable */ ip = &a /* Storage address of pointer variable */ fmt.Printf("a The address of the variable is: %x\n", &a ) /* Storage address of pointer variable */ fmt.Printf("ip Pointer address of variable storage: %x\n", ip ) /* Accessing values using pointers */ fmt.Printf("*ip Value of variable: %d\n", *ip ) }
Null pointer
When a pointer is defined and not assigned to any variable, its value is nil.
package main import "fmt" func main() { var ptr *int fmt.Printf("ptr The value of is : %x\n", ptr ) } Output result: ptr The value of is : 0
Null pointer judgment:
if(ptr != nil) /* ptr Not a null pointer */ if(ptr == nil) /* ptr Is a null pointer */
Integer pointer array
Pointer to pointer
If a pointer variable stores the address of another pointer variable, the pointer variable is called the pointer variable pointing to the pointer.
When defining a pointer variable pointing to a pointer, the first pointer stores the address of the second pointer and the second pointer stores the address of the variable:
The declaration format of pointer variable pointing to pointer is as follows:
var ptr **int; // Two * signs are required to access the pointer variable value pointing to the pointer
package main import "fmt" func main() { var a int var ptr *int var pptr **int a = 3000 /* Pointer ptr address */ ptr = &a /* Pointer ptr address */ pptr = &ptr /* Get the value of pptr */ fmt.Printf("variable a = %d\n", a ) fmt.Printf("Pointer variable *ptr = %d\n", *ptr ) fmt.Printf("Pointer to variable **pptr = %d\n", **pptr) } The execution output of the above example is: variable a = 3000 Pointer variable *ptr = 3000 Pointer variable to pointer **pptr = 3000
Go language structure
A structure is a data set composed of a series of data of the same type or different types.
Define structure:
Structure definition requires type and struct statements. Struct statement defines a new data type with one or more members in the structure. The type statement sets the name of the structure. The format of the structure is as follows:
type struct_variable_type struct { member definition member definition ... member definition } Once the structure type is defined, it can be used for variable declaration. The syntax format is as follows: variable_name := structure_variable_type {value1, value2...valuen} or variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { // Create a new structure fmt.Println(Books{"Go language", "www.runoob.com", "Go Language course", 6495407}) // You can also use the format key = > value fmt.Println(Books{title: "Go language", author: "www.runoob.com", subject: "Go Language course", book_id: 6495407}) // The ignored field is 0 or empty fmt.Println(Books{title: "Go language", author: "www.runoob.com"}) } The output result is: {Go language www.runoob.com Go Language tutorial 6495407} {Go language www.runoob.com Go Language tutorial 6495407} {Go language www.runoob.com 0}
Access structure members:
If you want to access structure members, you need to use a point number Operator, format:
structural morphology.member name
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { var Book1 Books /* Declare Book1 as a Books type */ var Book2 Books /* Declare Book2 as a Books type */ /* book 1 describe */ Book1.title = "Go language" Book1.author = "www.runoob.com" Book1.subject = "Go Language course" Book1.book_id = 6495407 /* book 2 describe */ Book2.title = "Python course" Book2.author = "www.runoob.com" Book2.subject = "Python Language course" Book2.book_id = 6495700 /* Print Book1 information */ fmt.Printf( "Book 1 title : %s\n", Book1.title) fmt.Printf( "Book 1 author : %s\n", Book1.author) fmt.Printf( "Book 1 subject : %s\n", Book1.subject) fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id) /* Print Book2 information */ fmt.Printf( "Book 2 title : %s\n", Book2.title) fmt.Printf( "Book 2 author : %s\n", Book2.author) fmt.Printf( "Book 2 subject : %s\n", Book2.subject) fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id) }
Structure as function parameter
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { var Book1 Books /* Declare Book1 as a Books type */ var Book2 Books /* Declare Book2 as a Books type */ /* book 1 describe */ Book1.title = "Go language" Book1.author = "www.runoob.com" Book1.subject = "Go Language course" Book1.book_id = 6495407 /* book 2 describe */ Book2.title = "Python course" Book2.author = "www.runoob.com" Book2.subject = "Python Language course" Book2.book_id = 6495700 /* Print Book1 information */ printBook(Book1) /* Print Book2 information */ printBook(Book2) } func printBook( book Books ) { fmt.Printf( "Book title : %s\n", book.title) fmt.Printf( "Book author : %s\n", book.author) fmt.Printf( "Book subject : %s\n", book.subject) fmt.Printf( "Book book_id : %d\n", book.book_id) }
Structure pointer
/* Print Book2 information */ printBook(&Book2) } func printBook( book *Books ) { fmt.Printf( "Book title : %s\n", book.title) fmt.Printf( "Book author : %s\n", book.author) fmt.Printf( "Book subject : %s\n", book.subject) fmt.Printf( "Book book_id : %d\n", book.book_id) }
Go language slice
The length of the go array cannot be changed, and such a set is not applicable in a specific scene. Go provides a flexible and powerful built-in type slice ("dynamic array"). Compared with the array, the length of the slice is not fixed, and elements can be added, which may increase the capacity of the slice.
Define slice
You can define slices by declaring an array of unspecified size:
var identifier []type
The slice does not need to specify the length.
Or use the make() function to create slices:
var slice1 []type = make([]type, len) It can also be abbreviated as slice1 := make([]type, len) s :=[] int {1,2,3 } Initialize the slice directly,[] Indicates the slice type,{1,2,3} The initialization values are 1 in turn,2,3,his cap=len=3.
You can also specify capacity, where capacity is an optional parameter.
make([]T, length, capacity)
s := arr[:] Initialize slice s,Is an array arr Reference to. s := arr[startIndex:endIndex] take arr Middle subscript startIndex reach endIndex-1 The element under is created as a new slice. s := arr[startIndex:] default endIndex Will indicate until arr The last element of the. s := arr[:endIndex] default startIndex Will indicate from arr Start with the first element of the. s1 := s[startIndex:endIndex] By slicing s Initialize slice s1. s :=make([]int,len,cap) Through built-in functions make() Initialize slice s,[]int Identified as its element type is int Slice of.
len() and cap() functions
Slices are indexable, and the length can be obtained by the len() method.
Slicing provides a method to calculate the capacity. cap() can measure the maximum length of slicing.
package main import "fmt" func main() { var numbers = make([]int,3,5) printSlice(numbers) } func printSlice(x []int){ fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) } The output result of the above example is: len=3 cap=5 slice=[0 0 0]
Empty slice
A slice defaults to nil and its length is 0 before initialization
var numbers []int
append() and copy() functions
package main import "fmt" func main() { var numbers []int printSlice(numbers) /* Allow appending empty slices */ numbers = append(numbers, 0) printSlice(numbers) /* Add an element to the slice */ numbers = append(numbers, 1) printSlice(numbers) /* Add multiple elements at the same time */ numbers = append(numbers, 2,3,4) printSlice(numbers) /* Creating slice numbers1 is twice the capacity of the previous slice*/ numbers1 := make([]int, len(numbers), (cap(numbers))*2) /* Copy the contents of numbers to numbers1 */ copy(numbers1,numbers) printSlice(numbers1) } func printSlice(x []int){ fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) }
The output result of the above code execution is:
len=0 cap=0 slice=[] len=1 cap=1 slice=[0] len=2 cap=2 slice=[0 1] len=5 cap=6 slice=[0 1 2 3 4] len=5 cap=12 slice=[0 1 2 3 4]
Go language Range
The range keyword in Go language is used to iterate the elements of array, slice, channel or map in the for loop. In the array and slice, it returns the index of the element and the value corresponding to the index, and returns the key value pair in the collection.
package main import "fmt" func main() { //This is how we use range to find the sum of a slice. Using arrays is similar to this nums := []int{2, 3, 4} sum := 0 for _, num := range nums { sum += num } fmt.Println("sum:", sum) //Pass in the values of range and index on the two variables. In the above example, we do not need to use the sequence number of the element, so we use the blank character "" Omitted. Sometimes we really need to know its index. for i, num := range nums { if num == 3 { fmt.Println("index:", i) } } //range can also be used on key value pairs of map. kvs := map[string]string{"a": "apple", "b": "banana"} for k, v := range kvs { fmt.Printf("%s -> %s\n", k, v) } //range can also be used to enumerate Unicode strings. The first parameter is the index of the character, and the second is the character (Unicode value) itself. for i, c := range "go" { fmt.Println(i, c) } }
Run output results:
sum: 9 index: 1 a -> apple b -> banana 0 103 1 111
Go language Map (set)
A Map is an unordered collection of key value pairs. The most important point of Map is to quickly retrieve data through key. Key is similar to index and points to the value of data.
Map is a collection, so we can iterate it like iterating arrays and slices. However, the map is out of order, and we cannot determine its return order, because the map is implemented using a hash table.
Define Map
You can use the built-in function make or the Map keyword to define the Map:
/* Declare variables. The default map is nil */ var map_variable map[key_data_type]value_data_type /* Using the make function */ map_variable := make(map[key_data_type]value_data_type)
If the map is not initialized, a nil map is created. Nil map cannot be used to store key value pairs
The following example demonstrates creating and using a map:
package main import "fmt" func main() { var countryCapitalMap map[string]string /*Create collection */ countryCapitalMap = make(map[string]string) /* map Insert the key - value pair and the corresponding capital of each country */ countryCapitalMap [ "France" ] = "Paris" countryCapitalMap [ "Italy" ] = "Rome" countryCapitalMap [ "Japan" ] = "Tokyo" countryCapitalMap [ "India " ] = "New Delhi" /*Use the key to output map values */ for country := range countryCapitalMap { fmt.Println(country, "The capital is", countryCapitalMap [country]) } /*Check whether the element exists in the collection */ capital, ok := countryCapitalMap [ "American" ] /*If it is determined to be true, it exists, otherwise it does not exist */ /*fmt.Println(capital) */ /*fmt.Println(ok) */ if (ok) { fmt.Println("American Our capital is", capital) } else { fmt.Println("American The capital of does not exist") } }
The running results of the above examples are:
France The capital is Paris Italy The capital is Rome Japan The capital is Tokyo India The capital is New Delhi American The capital of does not exist
delete() function
The delete() function is used to delete the elements of the collection. The parameters are map and its corresponding key. Examples are as follows:
ackage main import "fmt" func main() { /* Create map */ countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"} fmt.Println("Original map") /* Print map */ for country := range countryCapitalMap { fmt.Println(country, "The capital is", countryCapitalMap [ country ]) } /*Delete element*/ delete(countryCapitalMap, "France") fmt.Println("French entry deleted") fmt.Println("Map after deleting elements") /*Print map*/ for country := range countryCapitalMap { fmt.Println(country, "The capital is", countryCapitalMap [ country ]) } }
The running results of the above examples are:
Original map India The capital is New delhi France The capital is Paris Italy The capital is Rome Japan The capital is Tokyo French entry deleted Map after deleting elements Italy The capital is Rome Japan The capital is Tokyo India The capital is New delhi
Go language interface
Go language provides another data type, namely interface, which defines all common methods together. As long as any other type implements these methods, it implements this interface.
/* Define interface */ type interface_name interface { method_name1 [return_type] method_name2 [return_type] method_name3 [return_type] ... method_namen [return_type] } /* Define structure */ type struct_name struct { /* variables */ } /* Implementation interface method */ func (struct_name_variable struct_name) method_name1() [return_type] { /* Method implementation */ } ... func (struct_name_variable struct_name) method_namen() [return_type] { /* Method implementation*/ }
example
package main import ( "fmt" ) type Phone interface { call() } type NokiaPhone struct { } func (nokiaPhone NokiaPhone) call() { fmt.Println("I am Nokia, I can call you!") } type IPhone struct { } func (iPhone IPhone) call() { fmt.Println("I am iPhone, I can call you!") } func main() { var phone Phone phone = new(NokiaPhone) phone.call() phone = new(IPhone) phone.call() }
In the above example, we defined an interface Phone, which has a method call(). Then we define a Phone type variable in the main function and assign it to Nokia Phone and IPhone respectively. Then we call the call() method and output the result as follows:
I am Nokia, I can call you! I am iPhone, I can call you!
Go error handling
Go language provides a very simple error handling mechanism through the built-in error interface.
error type is an interface type, which is its own definition:
type error interface { Error() string } One Error()That is to return the corresponding error information with a string.
The most commonly used error related methods are 2:
1. Create error - FMT Some parameters of the Error() method, such as the information returned by the Error() method
2. Use error - since we define the output result of error as a String, when using error, once the details are involved, we can only use some String methods.
Specific examples:
Wrong implementation
1. For programs, error should include error details, such as error type, error code, etc., to facilitate transmission between modules
2. For people, error should include code information, such as relevant call parameters and operation information, so as to facilitate problem checking.
stack and wrap packaging
The first style: separate treatment
The second style: centralized processing
The third style: functional programming
- ContinueOnError indicates that the error encountered is only recorded, but the whole process continues to run down.
- BreakOnError means that if you encounter an error, you can break directly and don't run the next MyFunc
- One of the most intuitive features of functional programming is delayed execution, that is, it does not run when referring to MyFunc, and the real execution place is in ContinueOnError or BreakOnError.
Focus 1 - data structure
In the example, [] MyFunc is a slice, which can be simply understood as serial execution, that is, MyFunc executes one before executing the next.
Focus 2 - execution logic
Take ContinueOnError or BreakOnError as an example. They are the processing logic of various myfuncs.
Go concurrent channel
Go language supports concurrency. We only need to open goroutine through the go keyword.
Goroutine is a lightweight thread, and the scheduling of goroutine is managed by the Golang runtime.
goroutine syntax format:
go Function name( parameter list ) go f(x, y, z) Open a new goroutine: f(x, y, z)
Go allows you to use the go statement to start a new runtime thread, goroutine, to execute a function with a different, newly created goroutine. All goroutines in the same program share the same address space.
package main import ( "fmt" "time" ) func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } func main() { go say("world") say("hello") }
Execute the above code, and you will see that the output of hello and world are in no fixed order. Because they are executed by two goroutine s:
world hello hello world world hello hello world world hello
channel
A channel is a data structure used to transfer data.
Channel can be used for synchronous operation and communication between two goroutine s by passing a specified type of value. Operator < - used to specify the direction of the channel, send or receive. If no direction is specified, it is a two-way channel.
ch <- v // Send v to channel ch v := <-ch // Receive data from ch // And assign the value to v
It's easy to declare a channel. We can just use the chan keyword. The channel must be created before use:
ch := make(chan int)
Note: by default, channels are unbuffered. The sending end sends data, and there must be corresponding received data at the receiving end.
The following example uses two goroutines to calculate the sum of numbers. After goroutine completes the calculation, it will calculate the sum of the two results:
package main import "fmt" func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum += v } c <- sum // Send sum to channel c } func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c // Receive from channel c fmt.Println(x, y, x+y) }
The output result is:
-5 17 12
Channel buffer
The channel can set the buffer, and specify the buffer size through the second parameter of make:
ch := make(chan int, 100)
The channel with buffer allows the data transmission of the sender and the data acquisition of the receiver to be in an asynchronous state, that is, the data sent by the sender can be placed in the buffer and can wait for the receiver to obtain the data, rather than requiring the receiver to obtain the data immediately.
However, because the size of the buffer is limited, there must be a receiver to receive data. Otherwise, as soon as the buffer is full, the data sender cannot send data again.
Note: if the channel is not buffered, the sender will block until the receiver receives the value from the channel. If the channel is buffered, the sender will block until the transmitted value is copied into the buffer; If the buffer is full, it means waiting until a receiver gets a value. The receiver will be blocked until there is a value to receive.
package main import "fmt" func main() { // Here we define a buffered channel that can store integer types // The buffer size is 2 ch := make(chan int, 2) // Because ch is a buffered channel, we can send two data at the same time // You don't need to read data synchronously immediately ch <- 1 ch <- 2 // Get these two data fmt.Println(<-ch) fmt.Println(<-ch) } The execution output is: 1 2
Go traverse channel and close channel
Go traverses the read data through the range keyword, which is similar to array or slice. The format is as follows:
v, ok := <-ch
If ok is false after the channel cannot receive data, then the channel can be closed by using the close() function.
package main import ( "fmt" ) func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } close(c) } func main() { c := make(chan int, 10) go fibonacci(cap(c), c) // The range function iterates over the data received from each channel, because c is sending 10 // After the data, the channel is closed, so here our range function receives 10 data // Then it's over. If the c channel above is not closed, the range function is not closed // Will end, blocking when receiving the 11th data. for i := range c { fmt.Println(i) } } The execution output is: 0 1 1 2 3 5 8 13 21 34
The difference between Go and Python
We often use python to write some operation and maintenance tools. In the process of writing operation and maintenance tools in python, we find these problems:
- Write for a while and maintain the crematorium. It's too painful to read a slightly more complex script or a script written by others. It's hard to guess all kinds of parameters and formats in dict. You can only rely on print to see it many times.
- It is difficult to deploy. The strength of python lies in various rich libraries. When deploying, the lack of these libraries makes it impossible to run and forced
I tried to write operation and maintenance tools with go and found that it can solve these problems
- Statically compiled language, mandatory type checking. Use less interface {}. It's easy to maintain and read without guessing
- Static link, with cross compilation function, can basically compile at one time and run after copying