3 recently encountered Golang code issues

Source: Internet
Author: User
Tags parse error
This is a creation in Article, where the information may have evolved or changed.

For the last two weeks, I've been writing code with Golang in my spare time, and now I'm in a state where Golang is the only script. Anyway can use Golang realization, all write with Golang.

Golang language relatively mature, but really write up, or to pay attention to some "pit", the following is the three problems encountered this week, here to share, hoping to meet the same problem of children's shoes to help.

First, misuse of the timer, Mad CPU

Golang has a very idiomatic way to implement a timeout or tick timer via the channel, the code is as follows:

Func worker (start chan bool) {
for {
timeout: = time. After (* time. Second)
Select {
... do some stuff
Case <-Timeout:
Return
}
}
}

Func worker (start chan bool) {
for {
HEARTBEat: = time. Tick (* time. Second)
Select {
... do some stuff
Case <-Heartbeat:
Return
}
}
}

Yes, like these two examples above, if you execute them alone, you won't find any problems, but when you put such code in a 7 * 24-hour service, and the timeout interval or heartbeat interval is shorter, such as 1s, the problem arises.

My program was originally implemented with the above code to implement a Timewheel, by placing the timer in a separate goroutine to detect if the Timewheel has expired timer. The program ran in the background very well, until one night I inadvertently executed a top, I found this service actually stood with more than 40% CPU load. At first I wondered if there was a dead loop in the code, but after careful inspection of the code, no traces of the dead loop were found, and the algorithm logic was fine.

Then restarted the service and found that the CPU usage dropped down. Went out to the bathroom, back to continue with top observation, bad, this service occupies 1% of the CPU, and then rise to 2%, after observing a period of time, found that the service on the CPU occupancy rate over time and increase. GDB attach the corresponding process number, stack is the Go runtime scheduling.

Return to the code again and find that there may be a problem with only the tick here. My tick interval is 1s. So every 1s will create a runtime timer, and through the runtime source, these timer are thrown to the runtime scheduling (a heap). Long time, there will be more than the timer needs runtime scheduling, not consuming CPU is strange.

So the following changes were made:

Func worker (start chan bool) {
Heartbeat: = time. Tick (1* time. Second)
for {

Select {
... do some stuff
Case <-Heartbeat:
Return
}
}
}

Recompile the service and observe the day that the CPU has never been raised.

second, watch out for the list. Delete logic for list

In fact, this is a language in which you will encounter the primary problem, here just to give you a wake up. Not much to say, on the code:

From a list. The general logic for deleting an element in the list is:

L: = list. New ()
... ...
For e: = L.front (); E! = nil; E = E.next () {
If E.value. (int) = = Somevalue {
L.remove (e)
Return or break
}
}

But what if there are repeating elements in the list and the code goes through the list to delete an element with a value of somevalue? The general method above is made up of logical flaws, examples:

func foo (i int) {
L: = list. New ()
For I: = 0; I < 9; i++ {
L.pushback (i)
}
L.pushback (6)

For e: = L.front (); E! = nil; E = E.next () {
Fmt. Print (E.value. ( int))
}

For e: = L.front (); E! = nil; E = E.next () {
If E.value. (int) = = I {
L.remove (e)
}
}

Fmt. Printf ("\ n")
For e: = L.front (); E! = nil; E = E.next () {
Fmt. Print (E.value. ( int))
}
Fmt. Printf ("\ n")
}

Func Main () {
Foo (6)
}

The program attempted to delete all element with a value of 6 in the list, but the result was:

Go Run testlist.go
0123456786
012345786

The 6 of the tail of the list is not deleted, and the program seems to stop looping after the first 6 has been deleted. This is also true:

When L. After Remove (e) is executed, E.next () is set to nil so that the loop condition is no longer satisfied and the loop terminates.

For this reason, the following method is correct for such a program:

Func Main () {
Bar (6)
}

Func bar (i int) {
L: = list. New ()
For I: = 0; I < 9; i++ {
L.pushback (i)
}
L.pushback (6)

For e: = L.front (); E! = nil; E = E.next () {
Fmt. Print (E.value. ( int))
}

var next *list. Element
For e: = L.front (); E! = nil; {
If E.value. (int) = = I {
Next = E.next ()
L.remove (e)
E = Next
} else {
E = E.next ()
}
}

Fmt. Printf ("\ n")
For e: = L.front (); E! = nil; E = E.next () {
Fmt. Print (E.value. ( int))
}
Fmt. Printf ("\ n")
}

Execution Result:
$ go Run testlist.go
0123456786
01234578

Three, to give the template a correct name

To write a Web program, you need to use html/template.

... ...
T: = template. New ("My Reporter")
T, err = t.parsefiles ("views/report.html")
If err! = Nil {
W.writeheader (http. Statusinternalservererror)
Return
}

T.execute (W, userinfo{xx:xx})

As a result, the implementation was crash:

[Martini] Panic:runtime Error:invalid memory address or nil pointer dereference
/usr/local/go/src/runtime/panic.go:387 (0x16418)
/usr/local/go/src/runtime/panic.go:42 (0x1573e)
/usr/local/go/src/runtime/sigpanic_unix.go:26 (0X1BB50)
/usr/local/go/src/html/template/template.go:59 (0X7ED64)
/usr/local/go/src/html/template/template.go:75 (0x7ef0d)
/users/tony/test/gotoolsprojects/src/git.oschina.net/bigwhite/web/app.go:104 (0X2DB0)
Reporthandler:t.execute (W, userinfo{xx:xxx})

The problem is in T. Execute this line, separate the template code out in a test code:

Testtmpl.go
Type UserInfo struct {
Name string
}

Func Main () {
T: = template. New ("My Reporter")
T, err: = T.parsefiles ("views/report.html")
If err! = Nil {
Fmt. PRINTLN ("Parse error")
Return
}

Err = T.execute (OS. Stdout, Userinfo{name: "Tonybai"})
If err! = Nil {
Fmt. PRINTLN ("Exec error", err)
}
Return
}

Execution Result:
Go Run testtmpl.go
EXEC error template:my Reporter: "My Reporter" is an incomplete or empty template; Defined templates is: "Report.html"

It seems that the template object is not the same as the wrong name. Modify:

T: = template. New ("report.html")

Execution Result:





Hello, Tonybai.

This time, it seems that the name of the template is not random when used with parsefiles, it must be the same name as the templates file.

Parsefiles supports parsing multiple files, what if you are passing in multiple files? Godoc said that the template name is the same as the first file name.

Bigwhite. All rights reserved.

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.