Golang is one of my favorite languages. It’s simple, efficient, easy to learn, efficient to develop, and can be compiled into machine code… Although it was born, it has attracted a lot of attention, and now it is gradually popular in the market, but it is a new language, there are a lot of people not used to the place (pit, (^__^)), I as a novice, while learning, while stepping on pit, I hope to others for reference.

File names should not be used lightly__test.goTo the end

Golang’s source files are named the same as other languages, but Golang comes with Unit test, which has a minor specification: all Unit test files must end in __test.go! Go: no buildable go source files in XXXXXX(your file path) So, remember, the end of __test.go is the unit test file, and remember not to put the unit test file and go file together, must put the unit test file in the same directory, otherwise will not compile.

statementsFMT.Println(" here is the Chinese character :" + string variable)The value of a string variable cannot be printed

The following procedures are available:

Package main import "FMT" func main() {m1 := getString() fmt.println (" now :" + m1)} func getString()string{return "abd" }Copy the code

Run the command go run test.go

But the m1 variable printed alone will display normally

Import "FMT" func main() {m1 := getString() fmt.println (m1) fmt.println (" now :" + m1)} func getString()string{return "abd" }Copy the code

Why is that? It’s strange! In fact, this is due to the IDE, my IDE is a phpStorm + Golang plug-in package, the CONSOLE of THE IDE is very unfriendly to Chinese support, the string with Chinese is easy to display incomplete after printing, in fact, it is correct to print through terminal!

multipledeferWhen it appears, multipledeferIn LIFO (last in, first out) order

package main
import "fmt"
func main(){
    defer func(){
        fmt.Println("1")
    }()
    defer func(){
        fmt.Println("2")
    }()
    defer func(){
        fmt.Println("3")
    }()
}Copy the code

The corresponding output is:

3
2
1Copy the code

panicCan pass any value, not just string

package main import "fmt" func main(){ defer func(){ if r := recover(); r ! = nil{ fmt.Println(r) } }() panic([]int{12312}) }Copy the code

Output:

[12312]Copy the code

withfor rangeWhen traversing a list or map, the pointer to be traversed is invariant, and only a copy of the struct value is performed each traverse

import "fmt" type student struct{ Name string Age int } func main(){ var stus []student stus = []student{ {Name:"one", Age: 18}, {Name:"two", Age: 1},} 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

So, the resulting 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 called combination! Is combination!

import "fmt"
type student struct{
    Name string
    Age  int
}
func (p *student) love(){
    fmt.Println("love")
}
func (p *student) like(){
    fmt.Println("like first")
    p.love()
}
type boy struct {
    student
}
func (b * boy) love(){
    fmt.Println("hate")
}
func main(){
    b := boy{}
    b.like()
}Copy the code

Output:

like first
loveCopy the code

Regardless of the order in which you run it, when the parameters are functions, you evaluate the parameters first, okay

func main(){
    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:

1Copy the code

Pay attention to isstructPhi is a function of phi, or* structThe function of

import "fmt" type people interface { speak() } type student struct{ name string age int } func (stu *student) speak(){ fmt.Println("I am a student, I am ", stu.age) } func main(){ var p people p = student{name:"RyuGou", P = &student{name:"RyuGou", age:12} p.peak ()}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 to the data, the current Goruntine is blocked until someone receives it (i.e., “< -ch”), and if no one receives it, it stays blocked. If chan takes a buffer, it puts data into a buffer until the buffer is full and blocks

Import "FMT" func main(){ch := make(chan int) // ch := make(chan int, 1)Copy the code

Output:

fatal error: all goroutines are asleep - deadlock!Copy the code

Golang’s SELECT function is similar to that of select, poll, and epoll. It listens for I/O operations and triggers corresponding actions when I/O operations occur.

The code form of the select statement is very similar to that of the switch, except that the operation statement in the select case must be “IO operation” (not only <-channel, but also channel<-). The select statement will wait until a certain case is complete. Wait until the data is successfully read from the channel. The SELECT statement ends

 import "fmt"
func main(){
    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
successCopy the code

Default can determine 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
successCopy the code

At this time, since no data is written into CH, it is empty, so case cannot be read successfully. Select executes the default statement.

There are no uninitialized variables in Go

The basic method of variable definition is as follows:

Var Send volume name type = expressionCopy the code

Where both type and expression can be omitted, and if the initialization expression is omitted, the variable is initialized with a zero value.

  • A numeric variable corresponds to a value of 0
  • Boolean variables correspond to false
  • The zero value corresponding to a string is an empty string
  • Interface or reference type (slice, map, chan) variables correspond to nil
  • The zero value for an aggregate type such as an array or struct is the zero value for each element or field pair.
var s string 
fmt.Println(s) // ""Copy the code

: =Issues for attention

  • use: =A variable defined that can only be used inside a function.
  • When defining multiple variables: =Not everything around it is just declared, some of it may just be assigned, such as the err variable below
    in, err := os.Open(infile)
    // TODO
    out, err := os.Create(outfile)Copy the code

newIn the Go language it is just a predefined function, it is not a keyword, we can putnewAs a variable or something

Such as:

func delta(old, new int) int { 
    return new - old 
}Copy the code

That’s true.

It’s not about usingnewIt must allocate memory 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 using var or new.

Take an example:


var global *int 
func f() {
    var x int x=1 
    global = &x
}
func g() {
    y := new(int)
    *y = 1 
}Copy the code

The x in f() is allocated on the heap, while the Y in g() is allocated on the stack.

initFunctions can contain more than one function in the same file

You can have multiple init functions in the same package file, executed in the same order as they were defined.

Golang has no “objects”

package main
import (
    "fmt"
)
type test struct {
    name string
}
func (t *test) getName(){
    fmt.Println("hello world")
}
func main() {
    var t *test
    t = nil
    t.getName()
}Copy the code

Can it output normally? Will it report an error?

The output is:

hello worldCopy the code

It can output normally. Go is not an object-oriented language in nature, and there is no meaning of object in Go. Objects in Go language books are also different from objects in Java and PHP. They are not real “objects”, but entities of STRUCts in Go.

Method (t Type, arguments); getName (t Type, arguments);

func main() {
    (*test).getName(nil)
}Copy the code

Pointers in Go*Meaning of symbol

If you want to get the address of a variable, you just put an ampersand before the variable.

Such as:

a := 1
b := &aCopy the code

Now, I have the address of A, but I want to get the value that the pointer to A points to. What do I do? Use *, * B will do. * means to evaluate a pointer.

Add one to the value of A down here

a := 1
b := &a
*b++Copy the code

* and ampersand cancel each other out, and note that *& cancels out, but ampersand does not; So a is the same thing as star &a, and it’s the same thing as star &*&*& *&a.

os.ArgsGets command line instruction arguments, starting 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() {
    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 instruction./main 123

Output:. / main

The array slicing capacity problem brings a bug

Look at the following code:

import (
    "fmt"
)
func main(){
    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 the output? The answer is:

[10] 21Copy the code

NewSlice := append(append(slice, 50), 100), 150)

import (
    "fmt"
)
func main(){
    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 that? This starts with the expansion of Golang slices; If the slice capacity is less than 1024 elements, the cap of the slice will be doubled and multiplied by 2. Once the number of elements exceeds 1024, the growth factor becomes 1.25, or a quarter of the original capacity.) If the capacity of the original array is not reached after the expansion, then the position of the pointer in the slice is still the original array (this is the cause of the bug). If the size of the array exceeds the size of the original array, Go will create a new memory and copy the original values without affecting the original array at all. It is recommended to avoid bugs as much as possible.

mapNo error is reported when quoting a nonexistent key

What is the output of the following example? Will it report an error?

import (
    "fmt"
)
func main(){
    newMap := make(map[string]int)
    fmt.Println(newMap["a"])
}Copy the code

The answer is:

0Copy the code

Don’t complain. Unlike PHP, Golang’s map is similar to Java’s HashMap in that non-existent Java references return null, whereas Golang returns the initial value

Map uses range to iterate over the order problem, not the input order, but the random order

Look at the following example:


import (
    "fmt"
)
func main(){
    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 8Copy the code

It’s a random sequence. The map traversal order is not fixed. This design is intentional to prevent the program from relying on a specific traversal order.

Channel is passed as a function argument and can be declared to take only (< -chan) or send only (chan <-)

When declaring channel as an argument to a type, a function can declare channl either as a value (< -chan) or as a value (chan <-), unless otherwise specified.

For example, only values can be sent

func setData(ch chan <- string){
    //TODO
}Copy the code

If there is a <-ch in any of the above functions, the compilation fails.

The following values can only be:

func setData(ch <- chan  string){
    //TODO
}Copy the code

If ch<- exists in any of the above functions, an error is reported at compile time

When using channels, be aware of the execution flow between Goroutines

package main
import (
    "fmt"
)
func main(){
    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 send operation on an uncached channel will block the current goroutine and wait until another goroutine does the opposite. The flow in the above example looks like this:

The main goroutine waits to receive, and the other goroutine sends “test” and waits for processing; After the communication is complete, test is printed. Both Goroutines continue to run their own. The main goroutine waits to receive, and the other goroutine sends “Hello World” and waits for processing; When the communication is complete, print “Hello World”; Both Goroutines continue to run their own. The main goroutine waits to receive, and the other goroutine sends “123” and waits for processing; After the communication is complete, print “123”. Both Goroutines continue to run their own. The main goroutine waits to receive, and the other goroutine sends “456” and waits for processing; After the communication is complete, “456” is printed. Both Goroutines continue to run their own. The main goroutine waits to receive, and the other goroutine sends “789” and waits for processing; After the communication is complete, “789” is printed. Both Goroutines continue to run their own.

Remember: Golang’s channels are used to communicate between Goroutines, and they block.

Pit two for Go and pit three for Go