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.goTo 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!

multipledeferAppear when multipledeferIn 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

panicYou 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 rangeWhen 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 isstructPhi is a function of phi* structThe 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 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 usenewAs a variable or something

Such as:

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

That’s true.

It’s not usingnewMemory 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.

initMultiple 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.ArgsGets 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.

mapReference 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

For more exciting content, please follow my wechat official accountInternet Technology NestOr add wechat to discuss and communicate: