Golang is my favorite language. It is simple, efficient, easy to learn, efficient to develop, and can be compiled into machine code… Although it was born, has attracted a lot of attention, and now in the market gradually popular, but, it is a new language, there are a lot of people are not used to the place (pit, (^__^)), I as a novice, while learning, while stepping pit, hope to others have a reference.
Do not easily use the file name__test.go
To the end
Golang’s source files are named the same as any other language, but Golang comes with a Unit test, which has a small specification: all Unit test files must end with __test.go! So if you name a non-unit test file xxx_test. go and try to compile it, you will get the error: No buildable go source files in XXXXXX. Do not put the unit test files in the same directory as the normal go files. Otherwise, the unit test files will not compile properly.
statementsFMT.Println(" here is Chinese :" + string variable)
The value of a string variable cannot be printed
The following procedures are in place:
package main
import "fmt"
func main(a) {
m1 := getString()
fmt.Println("Now it is :" + m1)
}
func getString(a)string{
return "abd"
}
Copy the code
Run the go run test.go command
However, the variable M1 printed separately can be displayed normally
import "fmt"
func main(a) {
m1 := getString()
fmt.Println(m1)
fmt.Println("Now it is :" + m1)
}
func getString(a)string{
return "abd"
}
Copy the code
Why is that? It’s strange! My IDE is phpStorm + Golang plug-in package, and the CONSOLE of the IDE is not friendly to Chinese. It is easy to display incomplete strings with Chinese characters when printed out. In fact, it is correct to print them out by terminal!
multipledefer
Appear when multipledefer
In LIFO (last in, first out) order
package main
import "fmt"
func main(a){
defer func(a){
fmt.Println("1")
}()
defer func(a){
fmt.Println("2")
}()
defer func(a){
fmt.Println("3"()})}Copy the code
The corresponding output is:
3
2
1
Copy the code
panic
You can pass any value in, not just string
package main
import "fmt"
func main(a){
defer func(a){
if r := recover(a); r ! =nil{
fmt.Println(r)
}
}()
panic([]int{12312})}Copy the code
Output:
[12312]
Copy the code
withfor range
When traversing a set or map, the pointer being traversed is unchanged, and only a copy of the struct value is executed each time
import "fmt"
type student struct{
Name string
Age int
}
func main(a){
var stus []student
stus = []student{
{Name:"one", Age: 18},
{Name:"two", Age: 19},
}
data := make(map[int]*student)
for i, v := range stus{
data[i] = &v Data [I] = &stus[I]
}
for i, v := range data{
fmt.Printf("key=%d, value=%v \n", i,v)
}
}
Copy the code
Therefore, the result output is:
key=0, value=&{two 19}
key=1, value=&{two 19}
Copy the code
There is no inheritance in Go! No inheritance! Go is a combination! Is combination!
import "fmt"
type student struct{
Name string
Age int
}
func (p *student) love(a){
fmt.Println("love")}func (p *student) like(a){
fmt.Println("like first")
p.love()
}
type boy struct {
student
}
func (b * boy) love(a){
fmt.Println("hate")}func main(a){
b := boy{}
b.like()
}
Copy the code
Output:
like first
love
Copy the code
So, regardless of the order, when the argument is a function, you evaluate the argument first, right
func main(a){
a := 1
defer print(function(a))
a = 2;
}
func function(num int) int{
return num
}
func print(num int){
fmt.Println(num)
}
Copy the code
Output:
1
Copy the code
Pay attention to isstruct
Phi is a function of phi* struct
The function of
import "fmt"
type people interface {
speak()
}
type student struct{
name string
age int
}
func (stu *student) speak(a){
fmt.Println("I am a student, I am ", stu.age)
}
func main(a){
var p people
p = student{name:"RyuGou", age:12} P = &student{name:"RyuGou", age:12}
p.speak()
}
Copy the code
Output:
cannot use student literal (type student) as type people in assignment:
student does not implement people (speak method has pointer receiver)
Copy the code
make(chan int)
和 make(chan int, 1)
It’s different
Once chan has been written, the current goruntine is blocked until someone has received it (i.e., “< -ch”), and if no one has, it will remain blocked. If Chan has a buffer, it will put the data in the buffer and block until the buffer is full
import "fmt"
func main(a){
ch := make(chan int) // change to ch := make(chan int, 1)
ch <- 1
fmt.Println("success")}Copy the code
Output:
fatal error: all goroutines are asleep - deadlock!
Copy the code
Golang’s select function is similar to select, poll, and epoll, that is, it listens for IO operations and triggers the corresponding action when the IO operation occurs.
The select code is similar to the switch code, but the operation statement in the select case must be “IO operation “(not only the value <-channel, but also the assignment of channel<-). Select waits until a case statement is complete. Wait until the data is successfully read from the channel. Then the SELECT statement ends
import "fmt"
func main(a){
ch := make(chan int.1)
ch <- 1
select {
case msg :=<-ch:
fmt.Println(msg)
default:
fmt.Println("default")
}
fmt.Println("success")}Copy the code
Output:
1
success
Copy the code
Default determines if Chan is full
import "fmt"
func main(){
ch := make(chan int, 1)
select {
case msg :=<-ch:
fmt.Println(msg)
default:
fmt.Println("default")
}
fmt.Println("success")}Copy the code
Output:
default
success
Copy the code
In this case, no data is written in ch, so the case cannot be read successfully. Then select executes the default statement.
There are no uninitialized variables in Go
The basic way to define variables is:
Var issue name type = expressionCopy the code
Both the type and the expression can be omitted, and if the initialization expression is omitted, the variable is initialized with a zero value.
- A numerical variable corresponds to a value of 0
- The Boolean variable corresponds to false
- The zero value of a string is an empty string
- Interface or reference type variables (including Slice, map, chan) correspond to nil
- The zero value for an aggregate type such as an array or structure is the zero value for each element or field pair of that type.
var s string
fmt.Println(s) / / ""
Copy the code
: =
Questions for attention
- use
: =
Defined variables that can only be used inside functions. - When defining multiple variables
: =
Not all of the surrounding may be just declared, and some may just be assigned, such as the err variable belowin, err := os.Open(infile) // TODO out, err := os.Create(outfile) Copy the code
new
In the Go language, it is just a predefined function, it is not a keyword, we can usenew
As a variable or something
Such as:
func delta(old, new int) int {
return new - old
}
Copy the code
That’s true.
It’s not usingnew
Memory will definitely be allocated on the heap
The compiler automatically chooses whether to allocate storage on the stack or on the heap, but, perhaps surprisingly, this choice is not determined by how variables are declared with var or new.
Here’s an example:
var global *int
func f(a) {
var x int x=1
global = &x
}
func g(a) {
y := new(int)
*y = 1
}
Copy the code
The x in f() is allocated on the heap, and the y in g() is allocated on the stack.
init
Multiple functions can be contained in the same file
You can have multiple init functions in the same package file, and the init functions are executed in the same order as they were defined.
There is no object in Golang
package main
import (
"fmt"
)
type test struct {
name string
}
func (t *test) getName(a){
fmt.Println("hello world")}func main(a) {
var t *test
t = nil
t.getName()
}
Copy the code
Can it output normally? Will there be an error?
The output is:
hello world
Copy the code
Normal output is possible. In essence, Go is not an object-oriented language, and there is no meaning of object in Go. Objects in Go language books are different from objects in Java and PHP. They are not real “objects”, but entities of structs in Go.
Method (t Type, arguments) : Type. Method (t Type, arguments)
func main(a) {
(*test).getName(nil)}Copy the code
Pointer in Go*
Meaning of symbol
You know what ampersand means, take the address, if you want to get the address of a variable, just put an ampersand in front of the variable.
Such as:
a := 1
b := &a
Copy the code
Now, I’ve got the address of A, but I want to get the value that the pointer to a points to, so how do I do that? Use *, *b will do. The * is the value of the pointer.
So let’s add one to the value of A
a := 1
b := &a
*b++
Copy the code
* and & can cancel each other out, and notice that *& can cancel, but * * can’t; So a is the same as *&a, and it’s the same as *&*&*&a.
os.Args
Gets the command-line command arguments, which should start at the 1 coordinate of the array
The first element of os.args, os.args [0], is the name of the command itself
package main
import (
"fmt"
"os"
)
func main(a) {
fmt.Println(os.Args[0])}Copy the code
The above code, after go build, is packaged into an executable file main, and then run the./main 123 command
Output:. / main
A bug caused by the size of array slice slice
Look at the following code:
import (
"fmt"
)
func main(a){
array := [4]int{10.20.30.40}
slice := array[0:2]
newSlice := append(slice, 50)
newSlice[1] + =1
fmt.Println(slice)
}
Copy the code
What is output? The answer is:
[10] 21Copy the code
NewSlice := append(append(append(slice, 50), 100), 150);
import (
"fmt"
)
func main(a){
array := [4]int{10.20.30.40}
slice := array[0:2]
newSlice := append(append(append(slice, 50), 100), 150)
newSlice[1] + =1
fmt.Println(slice)
}
Copy the code
The output is:
20 [10]Copy the code
What the hell is this? This starts with the expansion of Golang slice; If the slice size is less than 1024 elements, then the cap of the slice is doubled by 2. Once the number of elements exceeds 1024, the growth factor becomes 1.25, increasing the original capacity by a quarter at a time.) If the capacity of the original array is not touched after the expansion, then the pointer in the slice points to the original array (this is the cause of the bug). If the capacity of the array exceeds the capacity of the original array, then Go will create a new memory and copy the original value, which will not affect the original array at all. It is recommended to avoid bugs as much as possible.
map
Reference to a nonexistent key without error
What is the output of the following example?
import (
"fmt"
)
func main(a){
newMap := make(map[string]int)
fmt.Println(newMap["a"])}Copy the code
The answer is:
0
Copy the code
Don’t complain. Unlike PHP, Golang’s map is similar to Java’s HashMap. If the Java reference does not exist, it returns null, while Golang returns the initial value
Map uses range to traverse the order problem, not the entry order, but the random order
Here’s an example:
import (
"fmt"
)
func main(a){
newMap := make(map[int]int)
for i := 0; i < 10; i++{
newMap[i] = i
}
for key, value := range newMap{
fmt.Printf("key is %d, value is %d\n", key, value)
}
}
Copy the code
Output:
key is 1, value is 1
key is 3, value is 3
key is 5, value is 5
key is 7, value is 7
key is 9, value is 9
key is 0, value is 0
key is 2, value is 2
key is 4, value is 4
key is 6, value is 6
key is 8, value is 8
Copy the code
It’s a chaotic sequence. The map traversal order is not fixed, which is intentionally designed to prevent the program from relying on a particular traversal order.
A channel is passed as a function argument and can be declared to take only (< -chan) or send only (chan <-).
A function declaring a channel as an argument to a type can declare channl as either a value (< -chan) or a value (chan <-). If not specified, it can either take a value or send a value.
For example, only values can be sent
func setData(ch chan <- string){
//TODO
}
Copy the code
If <-ch exists in any of the above functions, the compilation will fail.
The following values are available:
func setData(ch <- chan string){
//TODO
}
Copy the code
If there is a ch<- in any of these functions, an error will be reported at compile time
When using a channel, be aware of the flow of execution between goroutines
package main
import (
"fmt"
)
func main(a){
ch := make(chan string)
go setData(ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
fmt.Println(<-ch)
}
func setData(ch chan string){
ch <- "test"
ch <- "hello wolrd"
ch <- "123"
ch <- "456"
ch <- "789"
}
Copy the code
What is the execution flow of the above code? A send or value operation based on an uncached channel will cause the current goroutine to block and wait until another goroutine does the opposite. The process in the above example looks like this:
The main goroutine waits to be received, while the other goroutine sends “test” and waits for processing; When the communication is complete, print “test”; The two Goroutines continued to run their own. The main goroutine waits to be received. The other goroutine sends “Hello world” and waits to be processed. After completing the communication, print “Hello World”; The two Goroutines continued to run their own. The main goroutine waits for reception, the other goroutine sends “123” and waits for processing; After completing the communication, print out “123”; The two Goroutines continued to run their own. The main goroutine waits for reception, the other goroutine sends “456” and waits for processing; After completing the communication, print out “456”; The two Goroutines continued to run their own. The main goroutine waits for reception, while the other goroutine sends “789” and waits for processing; After completing the communication, print out “789”; The two Goroutines continued to run their own.
Remember: Golang’s channel is used for communication between Goroutines, and communication is blocked.
The pitfalls of Go
The pitfalls of Go