I used to be a Python developer, having written Python for about 5 years. Recently, I started learning and using Golang for a year. Although my work during this period wasn’t entirely coding-focused, my overall feelings about Golang come down to two main points:
- Development is indeed very convenient; it is worth studying in depth and mastering as a long-term programming language.
- It is easy to get started, but not simple to use well.
1. Development Efficiency and Ecological Advantages
Golang’s syntax is similar to Python, but its execution efficiency is higher. Its advantages include:
- Rich standard library
- Built-in high concurrency support
- Comprehensive testing and debugging tools
- Cross-platform compilation capability
- Active community and ecosystem (especially in the cloud-native field)
2. Error Handling: Simple but Requires Design
Golang uses error and panic to handle errors instead of an exception mechanism. Although this design has been criticized, the Golang team persists with it.
In Golang, error is an interface type, so it is very flexible. Common usage:
if err != nil {
return errors.New("some message")
}
While this works, it is not best practice. A better approach is to combine context information, for example:
if err != nil {
return fmt.Errorf("read config failed: %w", err)
}
Common problems:
- In a call chain (e.g., A → B → C), developers are unclear about which layer should handle the error.
- Using
if err.Error() == "xxx"to judge errors (poor maintainability). - Ignoring standard methods like
errors.Isanderrors.As.
Suggestion: Just like building blocks, use minimized error components and design them in combination with business logic, instead of errors.New() everywhere globally.
3. Interfaces: The Philosophy of Implicit Implementation
Unlike Java which requires explicit implements, Golang’s interfaces are implemented implicitly:
type Reader interface {
Read(p []byte) (n int, err error)
}
type File struct{}
func (f *File) Read(p []byte) (n int, err error) {
// Implementation details
return 0, nil
}
File does not explicitly declare that it implements Reader, but as long as the method signature matches, it implements it automatically.
Philosophical difference:
- Java: Design the interface, then implement it.
- Go: Discover the interface during implementation.
This design reduces unnecessary abstraction and avoids the anti-pattern of “interface for the sake of interface”.
4. Concurrency: The Double-Edged Sword of Goroutine and Channel
Goroutine and channel are the soul of Golang, making concurrent programming simple:
go func() {
fmt.Println("Hello from goroutine")
}()
But writing good concurrent programs is not easy: carelessness can cause deadlocks, ignoring the timing of channel closing can lead to goroutine leaks, and concurrency safety issues are easily overlooked.
Suggestions:
- Be familiar with the
syncpackage (WaitGroup,Mutex, etc.). - Avoid abusing shared memory.
- Clarify the lifecycle of channels.
5. Reflection and Growth
The ultimate goal of writing code is to make the program run, but what is more important after writing is to look back and think: What would you think if you looked at the code you wrote a year ago now? If you were asked to rewrite it, would you use the same implementation? The difference between a good programmer and an average programmer lies in whether they constantly reflect, summarize, and improve.
6. Conclusion
Golang is a language that is quick to get started with and highly efficient in execution, but to use it truly well, you need to understand the design philosophy behind it and constantly refine your skills in practice. Programming is not just about making the code “run”, but making it run well, run long, and run elegantly.