Hello everyone, I am fried fish.
I shared with you " Are you going to make these Go coding mistakes (1)?" ”, I don’t know how everyone has absorbed it, and have you stepped on a similar pit again?
Continue to come for the second bomb today, get on the train with the fried fish.
Go common mistakes
6. Scope of variables with the same name
question
When we write programs, we often use variable names such as n, i, err, etc. due to various temporary variables. Sometimes there are some problems, the following code:
func main() {
n := 0
if true {
n := 1
n++
}
fmt.Println(n)
}
What is the output of the program. Is n 1, or 2?
Output result:
0
Solution
The above code n := 1
declares a new variable again, which is a variable with the same name, and at the same time, it is very important that it contains a local variable with the same name.
Our n++
affects the variable n inside the if block, not the external variable n of the same name. If you want to affect correctly, it should be modified to:
func main() {
n := 0
if true {
n = 1
n++
}
fmt.Println(n)
}
Output result:
2
Although this case is not complicated in a single case, many Go beginners often encounter similar problems in the application when they are just getting started, and then ask why not...
According to the fish's 7s memory, this problem is encountered in the middle of the global DB handle, and there should be more than 10 times to ask the fried fish, which is a relatively high-frequency "pit".
7. Temporary variables in loops
question
I believe that many students have done similar things in business code, that is: while processing business data in a loop, while changing the value content.
The following code:
s := []int{1, 1, 1}
for _, n := range s {
n += 1
}
fmt.Println(s)
What is the output of the program, is i +1 all successful?
No, the real output is: [1 1 1]
.
Solution
In fact, in the loop, the variable we refer to is a temporary variable , and it is meaningless for you to modify it. What you modify is not the structure of your original data at all.
We need to locate the original data and locate and modify it according to the index. The following code:
s := []int{1, 1, 1}
for i := range s {
s[i] += 1
}
fmt.Println(s)
Output result:
[2 2 2]
This is very common, and if you don't pay attention, your hands will shake.
8. JSON conversion and output is empty
question
When doing data docking and conversion of external interfaces, we often need to process JSON data.
The following code:
type T struct {
name string
age int
}
func main() {
p := T{"煎鱼", 18}
jsonData, _ := json.Marshal(p)
fmt.Println(string(jsonData))
}
What is the output result? Can the name and age be output normally?
Output result:
{}
You read that right, the output of the program is empty and not converted to anything.
Solution
The reason is that JSON output will only output public (exported) fields, that is, the first letter must be capitalized.
We need to make the following changes:
type T struct {
Name string
Age int
}
func main() {
p := T{"煎鱼", 18}
jsonData, _ := json.Marshal(p)
...
}
Output result:
{"Name":"煎鱼","Age":18}
Or explicitly specify JSON tags:
type T struct {
Name string `json:"name"`
Age int `json:"age"`
}
Now the IDE can easily generate JSON tags directly. It is recommended that you habitually add them to ensure field specifications.
It can really avoid a lot of pulling and errors when docking.
9. Thinking that recovery is omnipotent
question
In Go, goroutine + panic + recover is a match made in heaven and it is very convenient to use. There are often students who think he is omnipotent.
The following code:
func gohead() {
go func() {
panic("煎鱼下班了")
}()
}
func main() {
go func() {
defer func() {
if r := recover(); r != nil {
fmt.Println(r)
}
}()
gohead()
}()
time.Sleep(time.Second)
}
What do you think the output will be. Was the program interrupted, or was it successfully recovered?
Output result:
panic: 煎鱼下班了
goroutine 17 [running]:
main.gohead.func1()
/Users/eddycjy/awesomeProject/main.go:10 +0x39
created by main.gohead
/Users/eddycjy/awesomeProject/main.go:9 +0x35
Do you think recovery is omnipotent? No.
Solution
There is no universal solution for Go1 at this stage, and it can only abide by Go's specifications ( Go cannot recover across goroutines, which is the correct logic ).
Goroutine recommends that each goroutine needs to have a recovery cover, otherwise once panic occurs, the application will be interrupted and the container will be restarted.
In addition, the fatal error throw actively thrown by the bottom layer of Go cannot be intercepted by recover, so please pay attention.
Note: Some students have always believed that recover can intercept throw, so hereby explain.
10. nil is not nil
question
When we do the logic processing of the program, we often need to judge the interface value.
The following code:
func Foo() error {
var err *os.PathError = nil
return err
}
func main() {
err := Foo()
fmt.Println(err)
fmt.Println(err == nil)
}
What do you think the output is, is it nil and true?
Output result:
<nil>
false
It looks nil on the surface, it is not equal to nil.
Solution
Interface value, is special. An interface value is equal to nil only if its value and dynamic type are both nil.
In the previous question code, actually the function Foo
returns [nil, *os.PathError]
, which we compare with [nil, nil]
, so it is false.
If you want to make an accurate judgment, you need to convert as follows:
fmt.Println(err == (*os.PathError)(nil))
The output will be true.
In addition, try to use the error type as much as possible, or avoid comparing with interface, which is a more dangerous behavior (many people do not know this phenomenon).
Summarize
In today's post, we started the second section of Common Coding Mistakes in Go, covering a total of 5 cases:
- The scope of the variable with the same name.
- Temporary variables in loops.
- JSON conversion and output is empty.
- I thought recovery was everything.
- nil is not nil.
This is still a very common case, have you encountered it? Or are there other new cases?
Welcome everyone to communicate and communicate together.
The article is updated continuously, you can read it by searching on WeChat [Brain fried fish]. This article has been included in GitHub github.com/eddycjy/blog . If you are learning Go language, you can see the Go learning map and route . Welcome to Star to urge you to update.
Recommended reading
- Introduction to the Go language series: a preliminary exploration of the actual combat of the Go project
- Go Programming Journey: Deep Dive into Go Projects
- Go Language Design Philosophy: Understanding Go Why and Design Thinking
- Go Language Advanced Tour: Go deeper into the Go source code
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。