Hello everyone, I am fried fish.
When making a new application selection, we will choose the application programming language. At this time, we will struggle with Java, PHP, Go, etc. We will think about whether there is a fatal problem and cannot be used?
It is clear that Go does not have a very fatal problem, otherwise you and I would not meet here, and there would be no fire.
There are quite a few uncomfortable points. Today, I will take a look at the fried fish with you.
uncomfortable point
Generics
Viewed on all social media and survey reports prior to Go1.18. The worst thing about Go is that it doesn't have generics.
To write a general method, either declare the input parameters as interface, or write N functions of the same code of different types, the code repetition rate is high.
As shown below:
This is the most uncomfortable point before Go1.18. Although the new version has generics, the supporting standards and open source libraries are not fully in place at this stage, and the impact will continue to exist.
Shallow copies and leaks
When writing Go programs, we often use basic types such as slice and map. But there is a more troublesome point, that is, it will involve shallow copy.
An inattentive will cause a BUG, the following code:
type T struct {
A string
B []string
}
func main() {
x := T{"煎鱼", []string{"上班"}}
y := x
y.A = "咸鱼"
y.B[0] = "下班"
fmt.Println(x)
fmt.Println(y)
}
What is the output?
Is Fried Fish at work or off?
The result is as follows:
{煎鱼 [下班]}
{咸鱼 [下班]}
In fact, at the time of y := x
, he copied the pointer to the object. At this time, the underlying data of x
and y
is actually a family, naturally a y
The fried fish of y
and x
also got off work.
The same type of slice also has the leakage of append and the inaccuracy of len and cap, which is more troublesome.
Leaked example:
var a []int
func f(b []int) []int {
a = b[:2]
return a
}
func main() {
...
}
If you are interested, you can read " Go slice causes memory leak and was pitted twice!" "Analysis.
error handling
In Go's error handling, the uncomfortable points of many small partners are divided into two parts. One is a lot of repeated code if err != nil
:
func main() {
x, err := foo()
if err != nil {
// handle error
}
y, err := foo()
if err != nil {
// handle error
}
z, err := foo()
if err != nil {
// handle error
}
s, err := foo()
if err != nil {
// handle error
}
}
The other part is in exception handling. Go is in panic and recover mode at this stage. It also contains throw fatal error throws, which cannot be intercepted. For this reason, I have also seen individual accidents caused by this.
This is a very controversial section.
nil interface is not nil
We forcibly assign the variable value of a Go program to nil, and make a judgment between nil and nil.
code show as below:
func main() {
var v interface{}
v = (*int)(nil)
fmt.Println(v == nil)
}
What is the result of the output. Is it false, true, or throws an exception?
The output is fasle
, nil may not be 100% equal to nil.
This is related to the internal data structure of the interface, and it is a detail that should be paid attention to when programming. For details, please refer to the analysis of " Go Interview Questions: A "Pit" and Principle Analysis of Go Interface" .
garbage collection
Go is very concise, the only thing that can be adjusted for garbage collection is the GC frequency, and the target percentage value of the initial garbage collector can be set through the GOGC variable.
$ GOGC=100 eddycjy
Simply put, the larger the value of GOGC is set, the lower the frequency of GC, but the heap memory that is eventually triggered to GC will be larger each time.
Then there is no other way to optimize the garbage collector itself, so much so that I was once ranted about Java and said that Go must have.
dependency management
The uncomfortable point of the finale is Go's dependency management. First from the GOPATH era, after the open source was not acclimatized, the rsc directly ended up and pushed hard.
By 2022, there will still be some uncomfortable points in Go modules. Even Cao Da summed up the "Seven Deadly Sins of Go mod", many of which I have encountered and solved for others in my work, which is very incisive.
Quoting the following 7 points:
- Side effects of the Go command: all go build, go list, and go test will pull resources outside the wall more or less, which will be very slow.
- The useless semver specification: the design of go mod is to hope that everyone must abide by the standard when the software library is released, such as maintaining compatibility in small versions. But this is very idealistic, and the reality is that there are often people who don't follow it.
- Can't deal with deleting the library: After the software library is released, you have already pulled it. But the publisher can still delete it, and it is still himself who is hurt.
- The implementation of goproxy is not uniform: the internal logic of several sets of goproxy written by author A, author B, and author C is not completely consistent, which is very frustrating.
- The lib version to go get is modified when go build.
- Diffusion of version information: The import path contains information such as version number v1, v2, etc. Once modified, it must be replaced in a large area.
- go.sum merge conflicts: multi-person maintenance on large projects, resulting in frequent conflicts.
One of the manifestations of being familiar with and mastering Go is to be proficient in Go modules, otherwise the project will not run smoothly.
Summarize
Today we analyzed and explained the uncomfortable scene of Go. This article involves: generics, shallow copy and leak, error handling, nil interface is not nil, garbage collection, dependency management.
Many of these are common, and some are intentional (eg: garbage collection). From everyone's point of view, what else do you think makes Go more uncomfortable?
Welcome to leave a message and exchange in the comment area.
The article is continuously updated, you can read it on WeChat by searching [Brain Fried Fish]. This article has been included in GitHub github.com/eddycjy/blog . To learn Go language, you can see the Go learning map and route . Welcome to Star to urge you to update.
Recommended reading
- Can you answer this Go question correctly? Over 80% of people got it wrong...
- Is there a need for Go return value naming?
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。