catalogue
Structure as function parameter
go language recursive function
Relationship between interface and type
go traverse and close channels
Learning material source: rookie tutorial
go language pointer
Address:
A variable is a convenient placeholder for referencing a computer's memory address.
The address fetching character of Go language is &. If it is used before a variable, the memory address of the corresponding variable will be returned.
Address of access variable in memory:
package main import "fmt" func main() { var a int = 10 fmt.Printf("Address of variable: %x\n", &a ) } /* The code output result is: Address of variable: 20818a220 */
Define pointer:
A pointer variable points to the memory address of a value.
Like variables and constants, you need to declare pointers before using them.
The format of pointer declaration is as follows:
var var_name *var-type
(VaR type is the pointer type, var_name is the pointer variable name, and the * sign is used to specify that the variable is used as a pointer.)
Valid pointer declaration:
var ip *int / * points to integer*/ var fp *float32 / * point to floating point*/
Use pointer:
Pointer usage process:
- Define pointer variables.
- Assign values to pointer variables.
- Access the value pointing to the address in the pointer variable.
(add a * sign (prefix) before the pointer type to get the content pointed to by the pointer.)
package main import "fmt" func main() { var a int= 20 /* Declare actual variables */ var ip *int /* Declare pointer variable */ ip = &a /* Storage address of pointer variable */ fmt.Printf("a The address of the variable is: %x\n", &a ) /* Storage address of pointer variable */ fmt.Printf("ip Pointer address of variable storage: %x\n", ip ) /* Accessing values using pointers */ fmt.Printf("*ip Value of variable: %d\n", *ip ) } /* a The address of the variable is 20818a220 ip Pointer address of variable storage: 20818a220 *ip Value of variable: 20 */
Null pointer:
When a pointer is defined and not assigned to any variable, its value is nil.
nil pointers are also called null pointers.
Like null, None, nil and null in other languages, nil conceptually refers to zero value or null value.
A pointer variable is usually abbreviated as ptr:
package main import "fmt" func main() { var ptr *int fmt.Printf("ptr The value of is : %x\n", ptr ) } //The value of ptr is: 0
Null pointer judgment:
If (PTR! = Nil) / * PTR is not a null pointer*/ If (PTR = = Nil) / * PTR is a null pointer*/
go language structure
In go language, we can define different data types for different items in the structure.
A structure is a data set composed of a series of data of the same type or different types.
Structure represents a record, such as the record of books in the library. Each book has the following attributes:
- Title: title
- Author: Author
- Subject: subject
- ID: Book ID
Define structure
Structure definition requires type and struct statements. The struct statement defines a new data type. There are one or more members in the structure. The type statement sets the name of the structure.
The format of the structure is as follows:
type struct_variable_type struct { member definition member definition ... member definition }
Once the structure type is defined, it can be used for variable declaration. The syntax format is as follows:
variable_name := structure_variable_type {value1, value2...valuen} or variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
Example:
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { // Create a new structure fmt.Println(Books{"Go language", "www.runoob.com", "Go Language course", 0}) // You can also use the format key = > value fmt.Println(Books{title: "Go language", author: "www.runoob.com", subject: "Go Language course", book_id: 0}) // The ignored field is 0 or empty fmt.Println(Books{title: "Go language", author: "www."}) } /* The output result is: {Go Language www.go language tutorial 0} {Go Language www.go language tutorial 0} {Go Language: www.0} */
Access structure members
If you want to access structure members, you need to use a point number Operator, format:
Structure Member name“
Example:
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { var Book1 Books /* Declare Book1 as a Books type */ var Book2 Books /* Declare Book2 as a Books type */ /* book 1 describe */ Book1.title = "Go language" Book1.author = "www.0" Book1.subject = "Go Language course" Book1.book_id = 0 /* book 2 describe */ Book2.title = "Python course" Book2.author = "www.0" Book2.subject = "Python Language course" Book2.book_id = 0 /* Print Book1 information */ fmt.Printf( "Book 1 title : %s\n", Book1.title) fmt.Printf( "Book 1 author : %s\n", Book1.author) fmt.Printf( "Book 1 subject : %s\n", Book1.subject) fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id) /* Print Book2 information */ fmt.Printf( "Book 2 title : %s\n", Book2.title) fmt.Printf( "Book 2 author : %s\n", Book2.author) fmt.Printf( "Book 2 subject : %s\n", Book2.subject) fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id) } /* Book 1 title : Go language Book 1 author : www. Book 1 subject : Go Language course Book 1 book_id : 0 Book 2 title : Python course Book 2 author : www. Book 2 subject : Python Language course Book 2 book_id : 0
Structure as function parameter
Pass the structure type as an argument to the function:
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { var Book1 Books /* Declare Book1 as a Books type */ var Book2 Books /* Declare Book2 as a Books type */ /* book 1 describe */ Book1.title = "Go language" Book1.author = "www." Book1.subject = "Go Language course" Book1.book_id = 0 /* book 2 describe */ Book2.title = "Python course" Book2.author = "www." Book2.subject = "Python Language course" Book2.book_id = 0 /* Print Book1 information */ printBook(Book1) /* Print Book2 information */ printBook(Book2) } func printBook( book Books ) { fmt.Printf( "Book title : %s\n", book.title) fmt.Printf( "Book author : %s\n", book.author) fmt.Printf( "Book subject : %s\n", book.subject) fmt.Printf( "Book book_id : %d\n", book.book_id) } /* The operation result is: Book title : Go language Book author : www. Book subject : Go Language course Book book_id : 0 Book title : Python course Book author : www. Book subject : Python Language course Book book_id : 0 */
Structure pointer
Defining a pointer to a structure is similar to other pointer variables. The format is as follows:
var struct_pointer *Books
Defining a pointer to a structure is similar to other pointer variables. The format is as follows:
var struct_pointer *Books
Use the structure pointer to access structure members, and use "." Operator:
struct_pointer.title
Example:
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { var Book1 Books /* Declare Book1 as a Books type */ var Book2 Books /* Declare Book2 as a Books type */ /* book 1 describe */ Book1.title = "Go language" Book1.author = "www." Book1.subject = "Go Language course" Book1.book_id = 0 /* book 2 describe */ Book2.title = "Python course" Book2.author = "www." Book2.subject = "Python Language course" Book2.book_id = 0 /* Print Book1 information */ printBook(&Book1) /* Print Book2 information */ printBook(&Book2) } func printBook( book *Books ) { fmt.Printf( "Book title : %s\n", book.title) fmt.Printf( "Book author : %s\n", book.author) fmt.Printf( "Book subject : %s\n", book.subject) fmt.Printf( "Book book_id : %d\n", book.book_id) } /* The execution and operation results of the above examples are as follows: Book title : Go language Book author : www. Book subject : Go Language course Book book_id : 0 Book title : Python course Book author : www. Book subject : Python Language course Book book_id : 0 */
go language recursive function
The syntax format of recursion (invoking itself in running) is as follows:
func recursion() {
recursion() / * function calls itself*/
}
func main() {
recursion()
}
be careful:
Go language supports recursion. But when we use recursion, developers need to set exit conditions, otherwise recursion will fall into an infinite loop. In mathematics, recursive function can calculate factorial, generate Fibonacci sequence and so on.
Factorial:
Use examples to understand:
package main import "fmt" func Factorial(n uint64)(result uint64) { if (n > 0) { result = n * Factorial(n-1) return result } return 1 } func main() { var i int = 15 fmt.Printf("%d The factorial of is %d\n", i, Factorial(uint64(i))) } /* The execution output of the above example is: 15 The factorial of is 1307674368000 */
Fibonacci sequence:
Example understanding:
package main import "fmt" func fibonacci(n int) int { if n < 2 { return n } return fibonacci(n-2) + fibonacci(n-1) } func main() { var i int for i = 0; i < 10; i++ { fmt.Printf("%d\t", fibonacci(i)) } } /* 0 1 1 2 3 5 8 13 21 34 */
go language type conversion
Type conversion is used to convert a variable of one data type to a variable of another type.
The basic format of Go language type conversion is as follows:
type_name(expression)
type_name is the type and expression is the expression.
example:
Convert an integer to a floating-point type, calculate the result, and assign the result to a floating-point variable.
package main import "fmt" func main() { var sum int = 17 var count int = 5 var mean float32 mean = float32(sum)/float32(count) fmt.Printf("mean The value of is: %f\n",mean) } /*mean The value of: 3.400000*/
go language interface
Go language provides another data type, interface (a set of standards). It defines all common methods together. As long as any other type implements these methods, it implements this interface.
Interface features: only method declarations, no fields.
/*Define interface*/
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
...
method_namen [return_type]
}
/*Define structure*/
type struct_name struct {
/* variables */
}
/*Implementation interface method*/
func (struct_name_variable struct_name) method_name1() [return_type] {
/ * method implementation*/
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
/ * method implementation*/
}
package main import ( "fmt" ) type Phone interface { call() } type NokiaPhone struct { } func (nokiaPhone NokiaPhone) call() { fmt.Println("I am Nokia, I can call you!") } type IPhone struct { } func (iPhone IPhone) call() { fmt.Println("I am iPhone, I can call you!") } func main() { var phone Phone phone = new(NokiaPhone) phone.call() phone = new(IPhone) phone.call() } /* The output results are as follows: I am Nokia, I can call you! I am iPhone, I can call you! */
In the above example, we defined an interface Phone, which has a method call(). Then we define a Phone type variable in the main function and assign it to Nokia Phone and IPhone respectively. Then we call the call() method.
Relationship between interface and type
One type can implement multiple interfaces (moile can be playusic and playvideo)
Multiple types can implement the same interface (cats and dogs are pets and can eat)
go error handling
Error type is an interface type. Error information is generated by implementing the error interface type in coding.
definition:
type error interface { Error() string }
Functions usually return error information in the last return value. Use errors New returns an error message:
package main import ( "fmt" ) // Define a DivideError structure type DivideError struct { dividee int divider int } // Implement the 'error' interface func (de *DivideError) Error() string { strFormat := ` Cannot proceed, the divider is zero. dividee: %d divider: 0 ` return fmt.Sprintf(strFormat, de.dividee) } // Define the function of division operation of type 'int' func Divide(varDividee int, varDivider int) (result int, errorMsg string) { if varDivider == 0 { dData := DivideError{ dividee: varDividee, divider: varDivider, } errorMsg = dData.Error() return } else { return varDividee / varDivider, "" } } func main() { // Normal condition if result, errorMsg := Divide(100, 10); errorMsg == "" { fmt.Println("100/10 = ", result) } // An error message is returned when the divisor is zero if _, errorMsg := Divide(100, 0); errorMsg != "" { fmt.Println("errorMsg is: ", errorMsg) } } /* The output result is: 100/10 = 10 errorMsg is: Cannot proceed, the divider is zero. dividee: 100 divider: 0 */
go concurrency
Go language supports concurrency. We only need to open goroutine through the go keyword.
Goroutine is a lightweight thread, and the scheduling of goroutine is managed by the Golang runtime.
goroutine syntax format:
go function name (parameter list)
Go allows you to use the go statement to start a new runtime thread, goroutine, to execute a function with a different, newly created goroutine. All goroutines in the same program share the same address space.
channel
A channel is a data structure used to transfer data.
Channel can be used for synchronous operation and communication between two goroutine s by passing a specified type of value. Operator < - used to specify the direction of the channel, send or receive. If no direction is specified, it is a two-way channel.
ch < - v / / send v to channel ch V: = < - ch / / receive data from ch //And assign the value to v
It's easy to declare a channel. We can just use the chan keyword. The channel must be created before use:
ch := make(chan int)
Note: by default, channels are unbuffered. The sending end sends data, and there must be corresponding received data at the receiving end.
Example:
Calculate the sum of numbers through two goroutines. After goroutine completes the calculation, it will calculate the sum of the two results:
package main import "fmt" func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum += v } c <- sum // Send sum to channel c } func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c // Receive from channel c fmt.Println(x, y, x+y) } /* The output result is: -5 17 12 */
Channel buffer
The channel can set the buffer, and specify the buffer size through the second parameter of make:
ch := make(chan int, 100)
The channel with buffer allows the data transmission of the sender and the data acquisition of the receiver to be in an asynchronous state, that is, the data sent by the sender can be placed in the buffer and can wait for the receiver to obtain the data, rather than requiring the receiver to obtain the data immediately.
However, because the size of the buffer is limited, there must be a receiver to receive data. Otherwise, as soon as the buffer is full, the data sender cannot send data again.
Note: if the channel is not buffered, the sender will block until the receiver receives the value from the channel. If the channel is buffered, the sender will block until the transmitted value is copied into the buffer; If the buffer is full, it means waiting until a receiver gets a value. The receiver will be blocked until there is a value to receive.
package main import "fmt" func main() { // Here we define a buffered channel that can store integer types // The buffer size is 2 ch := make(chan int, 2) // Because ch is a buffered channel, we can send two data at the same time // You don't need to read data synchronously immediately ch <- 1 ch <- 2 // Get these two data fmt.Println(<-ch) fmt.Println(<-ch) } /* The execution output is: 1 2 */
go traverse and close channels
Go traverses the read data through the range keyword, which is similar to array or slice. The format is as follows:
v, ok := <-ch
package main import ( "fmt" ) func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } close(c) } func main() { c := make(chan int, 10) go fibonacci(cap(c), c) // The range function iterates over the data received from each channel, because c is sending 10 // After the data, the channel is closed, so here our range function receives 10 data // Then it's over. If the c channel above is not closed, the range function is not closed // Will end, blocking when receiving the 11th data. for i := range c { fmt.Println(i) } } /* The execution output is: 0 1 1 2 3 5 8 13 21 34 */