Those pits of the go language

Source: Internet
Author: User

Golang is my favorite language, it is concise, efficient, easy to learn, the development of high efficiency, can also be compiled into machine code ...

Although it was born, and is now popular in the market, but it is a new language, there are many people are not very accustomed to the place (that is, the pit, (^__^)), I as a novice, while learning, while stepping on the pit, I hope to other people have reference role.

File names don't end with __test.go.

The naming of the Golang source file is not the same as in other languages, but Golang comes with unit test, and its unit test has a small specification: all unit test files end with __test.go!

So, when you name a non-unit test file as Xxx_test.go, and you are determined to compile, you will get an error: 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 normal go file together, be sure to put the unit test file into a directory, otherwise it will be compiled.

Statement FMT. Println ("Here is Kanji:" + string variable) The value of the string variable does not print out the problem

The following procedures are available:

Package Main

Import "FMT"

Func Main () {

M1: = GetString ()

Fmt. Println ("Now is:" + M1)

}

Func getString () string{

Return "Abd"

}

Run command go run test.go


But the individual print variable m1 can display normally

Import "FMT"

Func Main () {

M1: = GetString ()

Fmt. PRINTLN (M1)

Fmt. Println ("Now is:" + M1)

}

Func getString () string{

Return "Abd"

}

What is this for? It's strange!


In fact, this is to blame the IDE, my IDE is Phpstorm + Golang plug-in package, IDE comes with the console of Chinese support is very unfriendly, with Chinese characters printed out, easy to display, in fact, through the terminal print out, is correct!


When multiple defer occur, multiple defer are executed in 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")

}()

}

The corresponding output is:

3

2

1

You can pass any value in the panic, not just a string

Package Main

Import "FMT"

Func Main () {

Defer func () {

If r: = Recover (); r! = nil{

Fmt. Println (R)

}

}()

Panic ([]int{12312})

}

Output:

[12312]

When you use a for range to iterate over an array or map, the traversed pointer is constant, and each traversal executes only a copy of the struct value.

Import "FMT"

Type Student struct{

Name string

Age int

}

Func Main () {

var stus []student

Stus = []student{

{Name: "One", age:18},

{Name: "A", age:19},

}

Data: = Make (Map[int]*student)

For I, V: = Range stus{

Data[i] = &v//should be changed to: data[i] = &stus[i]

}

For I, V: = Range data{

Fmt. Printf ("key=%d, value=%v \ n", i,v)

}

}

Therefore, the result output is:

Key=0, Value=&{two 19}

Key=1, Value=&{two 19}

No inheritance in Go! No inheritance! Go is called combination! It's a 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 ()

}

Output:

Like first

Love

Regardless of the order of operation, when the parameter is a function, the value of the parameter is evaluated first

Func Main () {

A: = 1

Defer print (function (a))

A = 2;

}

func function (num int) int{

Return num

}

Func print (num int) {

Fmt. PRINTLN (num)

}

Output:

1

Note whether the function of a struct or a struct

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", age:12}//should be changed to P = &student{name: "Ryugou", Age:12}

P.speak ()

}

Output:

Cannot use student literal (type student) as type people in assignment:

Student does not implement people (speak method has pointer receiver)

Make (chan int) and make (chan int, 1) are not the same

Once Chan has been written to the data, the current goruntine will be blocked, knowing that someone can receive it (ie "<-ch") and it will keep blocking if no one receives it. And if Chan takes a buffer, it puts the data in the buffer until the buffer is full before it blocks.

Import "FMT"

Func Main () {

CH: = make (chan int)//change to ch: = Make (chan int, 1) just fine.

CH <-1

Fmt. PRINTLN ("Success")

}

Output:

Fatal Error:all Goroutines is asleep-deadlock!

The function of the Golang Select, similar to the Select, poll, Epoll, is to listen to the IO operation and trigger the corresponding action when the IO operation occurs.

The code form of select is very similar to switch, but the action statement in the Select Case can only be an "IO operation" (not just the value <-channel, the assignment channel<-), and select waits until a case The sentence is completed, that is, until the data is read successfully 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")

}

Output:

1

Success

Default can tell 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")

}

Output:

Default

Success

The case is not read successfully at this time because the data is not written in ch and is empty. The select executes the default statement.

Uninitialized variables are not present in the Go language

The basic way to define a variable is:

var sender name type = Expression

Both types and expressions can be omitted, and if an initialization expression is omitted, the variable is initialized with a value of 0.

A numeric variable corresponds to a value of 0.

Boolean variable corresponds to False

The 0 value of the string corresponds to an empty string

The interface or reference type (including the Slice,map,chan) variable corresponds to nil

The 0 value for an aggregation type, such as an array or struct, is a 0 value of the type that each element or field pair should be.

var s string

Fmt. PRINTLN (s)//""

: = Problem of attention

Use: = variable defined, can only be used inside the function.

When defining multiple variables: = Around is not necessarily all just declared, some may just be assignment, such as the following ERR variable

In, err: = OS. Open (infile)

Todo

Out, err: = OS. Create (outfile)

New is just a predefined function in the go language, it's not a keyword, we can use new as a variable or other

For example:

Func Delta (old, new int) int {

Return New-old

}

The above is correct.

Not using new will definitely allocate memory on the heap

The compiler will automatically choose to allocate storage space on the stack or on the heap, but it may be surprising that the choice is not determined by the way Var or new declares variables.

Take a look at the example:

var global *int

Func f () {

var x int X=1

Global = &x

}

Func g () {

Y: = new (int)

*y = 1

}

The x in the F () function allocates memory on the heap, and y in the G () function is allocated on the stack.

The init function can contain multiple files in the same file

In the same package file, you can include multiple init functions, and multiple init functions are executed in the same order as they are defined.

No "objects" in Golang

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 ()

}

Can you output it normally? Will it be an error?

The output is:

Hello World

can be output normally. Go is not object-oriented language, go is not the meaning of object, go language book objects and Java, PHP objects are different, not the real "object", is the entity of the struct in go.

Call the GetName method, you can also convert to: Type.method (t Type, arguments) in Go

So, the above code can also be written in the main function:

Func Main () {

(*test). GetName (Nil)

}

The meaning of the pointer * symbol in GO

& the meaning that everyone understands, take the address, if you want to get a variable address, just add & before the variable.

For example:

A: = 1

B: = &a

Now, I get the address of a, but I want to get the value of a pointer, how do I do it? With the * number, *b can be.

* means to take a value on the pointer.

The following adds a value to a

A: = 1

B: = &a

*b++

* and & can cancel each other, while note that,*& can be offset, but &* can not; So a and *&a are the same, and *&*&*&a is the same.

Os. Args Gets the command-line directive arguments, which should start with the 1 coordinate of the array

Os. The first element of args, the OS. Args[0], is the name of the command itself

Package Main

Import (

"FMT"

"OS"

)

Func Main () {

Fmt. Println (OS. Args[0])

}

The above code, after go build, is packaged into an executable file, main, and then run the instruction./main 123

Output:./main

Problem with the capacity of array slicing slice

Take a 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)

}

What is the output, please?

The answer is:

[10 21]

If slightly modified, the above newslice is changed to expand three times, Newslice: = Append (Append (Append (slice, 50), 100), 150) are as follows:

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)

}

The output is:

[10 20]

What the hell is this special?

This will start from the expansion of the Golang slice, the expansion of the slice, is when the slice added elements, the tile capacity is not enough, will be expanded, the size of the expansion follows the following principle: (If the tile capacity is less than 1024 elements, then the expansion of the slice cap will double, multiplied by 2 Once the number of elements exceeds 1024 elements, the growth factor becomes 1.25, which increases the original capacity by One-fourth each time. If the capacity of the original array has not been touched after the expansion, then the position of the pointer in the slice is still the original array (this is the cause of the bug), and if the capacity of the original array is exceeded after the expansion, then go will open a new memory and copy the original value. This situation does not affect the original array in the slightest.

It is recommended to avoid the creation of bugs as much as possible.

Map reference does not exist key, do not error

What does the following example output, will be an error?

Import (

"FMT"

)

Func Main () {

Newmap: = Make (Map[string]int)

Fmt. Println (newmap["a"])

}

The answer is:

0

No error. Unlike Php,golang's map and Java's HashMap, Java references that do not exist return NULL, and Golang returns the initial value

Map uses range to traverse order problems, not in order of entry, but in random order

Take a 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)

}

}

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

is in a disorderly order. Map traversal order is not fixed, this design is intentional, can prevent the program from relying on a particular traversal order.

The channel is passed as a function parameter and can be declared as a fetch only (<-Chan) or only sent (Chan <-)

When a function declares a channel as a parameter of a type, the CHANNL can be declared to be only a value (<-chan) or only a value (Chan <-) can be sent, and no special instructions can be taken to either value or send a value.

For example, you can only send values

Func setData (Ch chan <-string) {

Todo

}

If <-ch is present in the above function, it will compile without passing.

The following is the only value that can be taken:

Func setData (ch <-chan string) {

Todo

}

If ch<-is present in the above function, it will be error during compile time.

When using channel, pay attention to the execution flow problem between goroutine

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"

}

What is the execution flow of the above code?

A send or value operation based on a non-cached channel will cause the current goroutine to block and wait until another goroutine does the opposite or send the operation before it runs normally.

The process in the above example is this:

The main goroutine waits to receive, the other one goroutine sends "test" and waits for processing; After the communication is completed, the "test" is printed, and two goroutine continue to run their own.

The main goroutine waits to receive, the other goroutine sends "Hello World" and waits for processing; After the communication is finished, the "Hello World" is printed, and two goroutine continue to run their own.

The main goroutine waits to receive, the other one goroutine sends "123" and waits for processing; After completing the communication, print out "123"; two goroutine each continue to run their own.

The main goroutine waits to receive, the other one goroutine sends "456" and waits for processing; After completing the communication, print out "456"; two goroutine each continue to run their own.

The main goroutine waits to receive, the other one goroutine sends "789" and waits for processing; After completing the communication, print out "789"; two goroutine each continue to run their own.

Remember: The Golang channel is used to communicate between Goroutine and is blocked during communication.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.