introduction
Learn from other people’s mistakes, improve your Go programming skills by avoiding common pitfalls and bad habits with this guide
In Go, just like in any programming language, understanding common pitfalls and bad habits is the key to writing clean, efficient code.
Although some of the practices listed below are generally considered bad, in some cases they can be used effectively. This article aims to remind everyone of the problems of these practices and teach you how to avoid these pitfalls.
Let's dive into it in depth.
1. Use init()
In Go,init()
Functions are special functions executed before the main function.
“If initialization in any package is such an important process, why in Goinit()
Is it considered a bad practice? ” —— Reader
Yes, thoughinit()
Functions help initialize before running core logic, but their execution order can be difficult to understand. This may cause confusion about the initialization order.
If two modules depend on initialization and are in different packages, it may add complexity and require additional code to add waiting logic. However, this can also lead to the possibility of deadlock.
anotherinit()
The problem with the function is that it makes testing more difficult. Because they run automatically, it is difficult to control when they execute, which can make setting up test cases and testing code behavior challenging.
I'm having a problem that it takes 10 minutes for my service to go from deployment status to ready. I set a breakpoint on the first line of the main function, but it never fires.
We had to debug allinit()
Function, I found that a teammate was used in a "package I don't remember"init()
Functions, loading a lot of data from a large file into memory, which leads to a lot of time tracing a tiny problem.
2. Use global variables
This is similar to the problems that may arise when using singleton patterns, especially when global variables are complex, including maps, slices, or pointers.
Race condition: When using global variables, accessing global variables at the same time will lead to unexpected behavior. This is a big problem in Go.
Hard to test: Using global variables will make your project more stateful, which means that when you start unit testing/integration testing, the global variables must be the same as when you run main() or production.
Not modular enough and difficult to reuse: It is difficult to organize and encapsulate data because any package or module can access them. This can cause the code to be not modular enough and harder to understand, as it is difficult to determine where the data comes from and how to use them.
It is usually recommended to encapsulate your package so that it can be moved without affecting other packages. Using global variables may make your code tighter coupled, harder to modify or reuse.
3. Ignore error messages
Errors are inherent in Go programming, and it is important to handle them in an elegant way to ensure that no unexpected situations occur when errors occur.
The way to ignore error messages is to use the "_" symbol, doing so will discard the error value returned by the function, which may lead to unexpected behavior.
It is important to check for errors and handle them properly to prevent the program from crashing and crashing.
// sample 1 func main() { var x interface{} = "hello" s := x.(int) // panic: interface conversion: interface {} is string, not int (s) } // sample 2 func main() { var x interface{} = "hello" s, _ := x.(int) // safe but DON'T (s) }
Ignoring error handling can lead to major problems in production code, as this can make it difficult to identify and fix errors. Always check for errors and fixing them properly are important to ensure smooth running of your code.
4. GOTO statement — jump into a trap
Not only in Go, many languages consider using "goto" statements as a bad practice because it makes the code harder to understand and maintain.
The reason is that the "goto" statement ignores the code flow, making it difficult to understand the dependencies between different parts of the code without introducing an error.
This may make it difficult to reason the state of the program at runtime, making debugging and testing more difficult.
Using "goto" can lead to an increase in the number of errors, making it harder to identify the root cause of the problem.
5. Don't use Defer and Recover
The main reason for using "defer" and "recover" is to prevent panic. "defer" can even be executed when panic occurs, while "recover" can capture panic, allowing for more control to handle unexpected situations.
This usage is considered bad code practice:
func readFile(filename string) { file, err := (filename) if err != nil { panic(err) } // Do something with the file () // <--- DONT }
We usedefer
This way, evenreadFile()
When the function appears panic, the file will also be closed. In addition, it is easy to remember to do soopen()
The function is immediately placed after it.
func readFile(filename string) { file, err := (filename) if err != nil { (err) } defer () // Do something with the file ... }
6. Use too many times ()
In Go, context is one of the most powerful features. When used correctly, it can serve as a provider, tree stream and flow controller.
When making external calls (such as databases, HTTP, etc.), use()
or()
It is very important to set a deadline or timeout. If not set, bottlenecks may occur in your application when there are too many users and external services do not respond in a timely manner.
I usually write a practical function for a context pool that includes 3 functions to create or wrap new contexts with timeouts: fast (0.5 seconds), medium (3 seconds), slow (10 seconds). That way, I don't have to rely on it all the time()
, and it is easy to set the appropriate timeout for each call.
const FastTimeout = 500 * func WrapCustomContext(ctx , dur ) (, ) { return ((), dur) } func GenFastContext() (, ) { return WrapCustomContext((), FastTimeout) } func WrapFastContext(ctx ) (, ) { return WrapCustomContext(ctx, FastTimeout) }
The above is the detailed content of learning to correct bad Go language habits and improving programming skills from mistakes. For more information about Go language programming habits, please pay attention to my other related articles!