Is the popular Golang really a panacea in back-end development?

Is the popular Golang really a panacea in back-end development?

Preface

People outside the city want to go in, people in the city want to come out. - Qian Zhongshu, "The Besieged City"

As container orchestration (Container Orchestration), micro services (Micro Services), cloud technology (Cloud Technology), etc. continue to prevail in the IT industry, Golang (Go language, referred to as Go), which was born at Google in 2009, has become more and more popular among software engineers. Welcome and sought after, it has become the most popular back-end programming language today. In the list of software projects developed with Golang, there are star-rated products such as Docker (container technology) and Kubernetes (container orchestration) that subvert the entire IT industry, as well as Prometheus (monitoring system), Etcd (distributed storage), InfluxDB ( Time series database) such a powerful and practical well-known project. Of course, the application areas of the Go language are by no means limited to containers and distributed systems. Nowadays, many large Internet companies use Golang extensively to build back-end web applications, such as Toutiao, JD, Qiniu Cloud, etc.; the framework crawler field dominated by Python for a long time has also been continuously influenced by Golang because of the rise of the simple and easy-to-use crawler framework Colly Challenge. Golang has become the programming language most software engineers want to learn today. The picture below is HackerRank the relevant results survey of programmer skills in 2020.

So, is the Go language really a life-saving medicine for back-end developers? Can it effectively improve the technical strength and development efficiency of programmers, thereby helping them to go further in the workplace? Is Go language really worth our time to study in depth? **This article will introduce Golang's language features, its advantages, disadvantages and applicable scenarios in detail. With the above questions, I will analyze all aspects of the Go language for readers to help programmers who are new to the IT industry and those who are interested in Go. Developers learn more about this popular language.

Introduction to Golang

Golang was born in the Internet giant Google, and this is not a coincidence. We all know that Google has a corporate culture of 20% doing side projects (Side Project), allowing engineers to create disruptive and innovative products in a relaxed environment. And Golang has been continuously hatched during this 20% of the time. The founder of the Go language is also a well-known industry leader in the IT industry, including Rob Pike, a member of the Unix core team, Ken Thompson, the author of the C language, and Robert Griesemer, a core contributor to the V8 engine. The popularity of the Go language by the public is still due to the explosive development of container technology Docker after it was open sourced in 2014. Since then, the Go language has been sought after by a large number of developers because of its simple syntax and fast compilation speed, and many excellent projects have also been born, such as Kubernetes.

Compared with other traditional popular programming languages, Go language has many advantages, especially its efficient compilation speed and natural concurrency characteristics , making it the language of choice for rapid development of distributed applications . Go language is a statically typed language , which means that Go language needs to be compiled like Java and C#, and has a complete type system, which can effectively reduce code quality problems caused by inconsistent types . Therefore, the Go language is very suitable for building stability and flexibility large-scale IT systems that require . This is also an important reason why many large Internet companies use Golang to reconstruct old code: the stability of traditional static OOP languages (such as Java, C#) High but lack of flexibility; while dynamic languages (such as PHP, Python, Ruby, Node.js) are flexible but lack stability. Therefore, it is natural that Golang, which has "bear's paw and fish", is sought after by developers. After all, "the world is suffering for Java/PHP/Python/Ruby for a long time".

However, the Go language is not without its shortcomings . Using dialectical thinking, it can be speculated that some outstanding features of Golang will become its double-edged sword. For example, the advantages of Golang's simple syntax will limit its ability to handle complex problems. In particular, the lack of Generics in the Go language has greatly increased the complexity of building a general framework. Although this outstanding problem is likely to be effectively solved in version 2.0, it also reflects that star programming languages will also have shortcomings. Of course, the shortcomings of Go do not stop there. Go language users will also complain about its verbose error handling (Error Handling), lack of strict constraints on duck typing (Duck Typing), date format issues, etc. Below, we will start with the characteristics of the Golang language, and analyze the advantages and disadvantages of Golang and the application scenarios of the project from the shallower to the deeper.

Language Features

Concise grammatical features

The syntax of the Go language is very simple, at least very concise in terms of variable declarations, structure declarations, function definitions, etc.

Variable declaration is not as verbose as Java or C, it can be used in Golang

:=
This syntax is used to declare new variables. For example, the following example, when you directly use
:=
When defining a variable, Go will automatically declare the type of the assignment object as the type of the assignment source, which saves a lot of code.

func main () { valInt := 1 //Automatically infer int type valStr := "hello" //Automatically infer as string type valBool := false //Automatically infer as bool type } Copy code

Golang also has a lot to save you code. You can find that Go is not mandatory

new
This keyword is used to generate a new instance (Instance) of a certain class (Class). Moreover, the conventions for public and private properties (variables and methods) no longer use the traditional
public
with
private
Keywords, but directly use the case of the first letter of the attribute variable to distinguish. The following examples can help readers understand these characteristics.

//Define a struct class type SomeClass struct { PublicVariable string //public variable privateVariable string //private variable } //Public method func (c *SomeClass) PublicMethod () (result string ) { return "This can be called by external modules" } //private method func (c *SomeClass) privateMethod () (result string ) { return "This can only be called in SomeClass" } func main () { //Generate instance someInstance := SomeClass{ PublicVariable: "hello" , privateVariable: "world" , } } Copy code

If you use Java to implement the above example, you may see verbose

.java
Class files, for example.

//SomeClass.java public SomeClass { public String PublicVariable; //public variable private String privateVariable; //private variable //Constructor public SomeClass (String val1, String val2) { this .PublicVariable = val1; this .privateVariable = val2; } //public method public String PublicMethod () { return "This can be called by external modules" ; } //private method public String privateMethod () { return "This can only be called in SomeClass" ; } } ... //Application.java public Application { public static void main (String[] args) { //Generate instance SomeClass someInstance = new SomeClass( "hello" , "world" ); } } Copy code

As you can see, in addition to the multi-layer curly braces that are easy to see in the Java code, there are also a lot of

public
,
private
,
static
,
this
The keywords used for modification are very verbose; while the Golang code relies on simple conventions, such as the capitalization of the first letter, to avoid many repetitive modifiers. Of course, Java and Go still have some differences in the type system, which also makes Go seem a little weak in dealing with complex problems. This is something that will be discussed later. In short, the conclusion is that Go's syntax is very concise in a statically typed programming language.

Built-in concurrent programming

In addition to its powerful performance, the Go language has become the first choice for distributed applications. The main reason is its natural concurrent programming. This concurrent programming feature mainly comes from the Golang (Goroutine) and channel (Channel). The following is an example of using coroutines.

func asyncTask () { fmt.Printf( "This is an asynchronized task" ) } func syncTask () { fmt.Printf( "This is a synchronized task" ) } func main () { go asyncTask() //execute asynchronously without blocking syncTask() //execute synchronously, block go asyncTask() //wait for the completion of the previous syncTask, then execute asynchronously without blocking } Copy code

As you can see, the keywords

go
Adding a function call allows it to be executed as an asynchronous function without blocking the code behind. And if you don't add
go
Keywords will be treated as synchronous code execution. If the reader is familiar with JavaScript
async/await
,
Promise
Syntax, even multi-threaded asynchronous programming in Java and Python, you will find that they are not as simple as Go asynchronous programming!

Asynchronous functions, that is, communication between coroutines, can be implemented using channels unique to the Go language. The following is an example of a channel.

func longTask (signal chan int ) { //for without parameters //equivalent to a while loop for { //receive signal channel value v := <- signal //If the received value is 1, stop the loop if v == 1 { break } time.Sleep( 1 * Second) } } func main () { //declare channel sig := make ( chan int ) //call longTask asynchronously go longTask(sig) //wait for 1 second time.Sleep( 1 * time.Second) //Pass value sig <- 1 to channel sig //Then longTask will receive the sig transfer value and terminate the loop } Copy code

Interface-oriented programming

Go language is not strictly object-oriented programming (OOP), it uses interface-oriented programming (IOP), which is a more advanced programming model than OOP. As a part of the OOP system, IOP places more emphasis on rules and constraints, as well as the conventions of interface types and methods, so that developers can focus on more abstract program logic as much as possible, instead of wasting time on more detailed implementations. Many large projects use the IOP programming model. If you want to learn more about interface-oriented programming, please check the previous article "Why TypeScript is a necessary language for developing large-scale front-end projects " in the personal technology blog of "Code Way " , which contains a detailed explanation of interface-oriented programming.

Like TypeScript, Go language also uses the duck type method to verify interface inheritance. The following example can describe the duck type characteristics of the Go language.

//Define the Animal interface interface Animal { Eat() //Declare Eat method Move() //Declare Move method } //==== Define Dog Start ==== //Define Dog type Dog struct { } //Implement the Eat method func (d *Dog) Eat () { fmt.Printf( "Eating bones" ) } //Implement the Move method func (d *Dog) Move () { fmt.Printf( "Moving with four legs" ) } //==== Define Dog End ==== //==== Define Human Start ==== //Define Human class type Human struct { } //Implement the Eat method func (h *Human) Eat () { fmt.Printf( "Eating rice" ) } //Implement the Move method func (h *Human) Move () { fmt.Printf( "Moving with two legs" ) } //==== Define Human End ==== Copy code

As you can see, although the Go language can define interfaces, unlike Java, Go language does not display the keyword modification syntax for declaring the implementation of the interface (Implementation). In Go language, if you want to inherit an interface, you only need to implement all the methods declared by the interface in the structure. In this way, for the Go compiler, the class you define is equivalent to inheriting the interface. In this example, we stipulate that as long as something can eat (Eat) and can move (Move) is an animal (Animal). Dogs and humans happen to be able to eat and move, so they are both counted as animals. This inheritance method that relies on the matching degree of the implementation method is the duck type: if an animal looks like a duck and calls like a duck, then it must be a duck. This duck type is more flexible than traditional OOP programming languages. However, as we will discuss later, this programming method will bring some trouble.

Error handling

Error handling in Go is notoriously long-winded. Here is a simple example first.

package main import "fmt" func isValid (text string ) (valid bool , err error) { if text == "" { return false , error( "text cannot be empty" ) } return text == "valid text" , nil } func validateForm (form map [ string ] string ) (res bool , err error) { for _, text := range form { valid, err := isValid(text) if err != nil { return false , err } if !valid { return false , nil } } return true , nil } func submitForm (form map [ string ] string ) (err error) { if res, err := validateForm(form); err != nil || !res { return error( "submit error" ) } fmt.Printf( "submitted" ) return nil } func main () { form := map [ string ] string { "field1" : "" , "field2" : "invalid text" , "field2" : "valid text" , } if err := submitForm(form); err != nil { panic (err) } } Copy code

Although the entire code above is fictitious, it can be seen that the Go code is full of

if err := ...; err != nil {...}
Wrong judgment statement like this. This is because the Go language requires developers to manage errors themselves, that is, errors in functions need to be explicitly thrown, otherwise the Go program will not do any error handling. Because Go has no traditional programming language
try/catch
The syntax for error handling, so lack of flexibility in error management, led to "
err
"Flying all over the sky" situation.

However, the law of dialectics tells us that this approach is also beneficial. 1. it forces Go language developers to standardize error management methods from the code level, which drives developers to write more robust code; second, this way of explicitly returning errors avoids "

try/catch
"A shuttle", because this "temporarily cool" approach may lead to bugs that cannot be accurately located, resulting in many unpredictable problems; third, because there is no
try/catch
With brackets or extra code blocks, the Go program code looks cleaner and more readable as a whole.

other

Go language certainly has many other features, but the author believes that the above features are more distinctive in the Go language, and they are more distinguishable features. Other features of Go language include but are not limited to the following.

  • Fast compilation
  • Cross-platform
  • defer
    Delayed execution
  • select/case
    Channel selection
  • Compile directly into executable program
  • Unconventional dependency management (you can directly reference the Github repository as a dependency, for example
    import "github.com/crawlab-team/go-trace"
    )
  • Unconventional date format (the format is "2006-01-02 15:04:05", you read it right, it is said that this is the founding time of Golang!)

Overview of advantages and disadvantages

I have introduced many language features of Go earlier, and readers must have a basic understanding of Golang. Some of the language features also hint at its advantages and disadvantages relative to other programming languages. Although the Go language is very popular now, while praising and embracing Golang, I have to understand some of its shortcomings.

The author here does not intend to analyze the pros and cons of the Go language in a long form, but to enumerate some of the relevant facts, and the reader can judge for themselves. The following is an incomplete comparison list of the advantages and disadvantages of Golang language features summarized by the author.

characteristic advantage Disadvantage
Simple syntax Improve development efficiency and save time Difficult to deal with some complex engineering problems
Concurrency is naturally supported Greatly reduce the difficulty of asynchronous programming and improve development efficiency Developers who are not familiar with channels and coroutines will have some learning costs
Type system
  • Go language is statically typed, which is more stable and predictable than dynamically typed languages
  • IOP duck type is more concise than strict OOP language
    • No inheritance, abstraction, static, dynamic and other characteristics
    • Lack of generics, resulting in reduced flexibility
    • Difficult to quickly build complex and general frameworks or tools
    Error handling Mandatory constraint error management to avoid "
    try/catch
    A shuttle"
    Long-winded error handling code, flooded with
    if err := ...
    Fast compilation This is definitely an advantage How could it be a disadvantage?
    Unconventional dependency management
    • You can directly reference repositories published on Github as module dependency references, eliminating the need for official websites that rely on hosting
    • You can publish third-party modules written in Go language on Github at any time
    • Free dependent release means that the ecological development of Golang will not be restricted by the official dependent hosting website
    Relying heavily on Github, searching for Go language modules on Github is relatively inaccurate
    Unconventional date format According to 6-1-2-3-4-5 (2006-01-02 15:04:05), it is relatively easy to remember For developers who are accustomed to the yyyy-MM-dd HH:mm:ss format, they are very unaccustomed

    In fact, each characteristic has its own advantages and disadvantages in a certain situation, and cannot be generalized. Just like the static type and interface-oriented programming adopted by the Go language, there is no lack of type constraints, nor is it as tedious and complicated as strict OOP. It is a modern programming language that is between a dynamic language and a traditional static type OOP language. While this positioning improves the efficiency of Golang development, it also castrates a lot of necessary OOP syntax features, and thus lacks the ability to quickly build a general engineering framework (this is not to say that Go cannot build a general framework, but it is not as easy as Java and C#). In addition, the "wonderful" error handling specifications of the Go language make Go developers love and hate: they can develop more robust applications, but at the same time they sacrifice the simplicity of a part of the code. You know, the design philosophy of Go language is to "simplify the road to simplicity", so the design is as simple as possible while pursuing high performance.

    It is undeniable that the built-in concurrency support of the Go language is a very innovative feature in recent years, which is also an important reason why it is widely adopted by distributed systems. At the same time, it is very fast compared to Java that compiles easily for more than ten minutes. In addition, the Go language does not sacrifice stability because of its simple syntax; on the contrary, it regulates the code style of the entire Go project from simple constraints. Therefore, **"Fast", "Concise", and "Robust"** are the design goals of the Go language. In the process of learning Golang, we can't accept everything about it without thinking, but should judge its application in actual projects based on its own characteristics.

    Applicable scene

    After discussing the various dimensions of Golang in the previous article, we can conclude that the Go language is not a panacea for back-end development . In actual development work, developers should avoid using Golang as a back-end development language under no circumstances. On the contrary, engineers should fully understand all aspects of the candidate technology (language, framework or architecture) before deciding on the technology selection, including the degree of fit between the candidate technology and business requirements, integration with the development team, and its learning, development, time cost, etc. Factors . After learning some programming languages, including the front and back ends, I found that they each have their own advantages and corresponding disadvantages.If a programming language can be widely known, it will definitely not be a bad language . Therefore, the author will not assert that "XXX is the best language in the world", but will share with readers personal thoughts on technology selection in specific application scenarios. Of course, this article is a technical article for the Go language. Next, I will share the application scenarios that I personally think Golang is most suitable for.

    Distributed application

    Golang is very suitable for development in distributed application scenarios. The main purpose of distributed applications is to use as much computing resources and network bandwidth as possible to maximize the overall performance and efficiency of the system. Among them, an important demand function is concurrency. And Go is a leader in supporting high concurrency and asynchronous programming . As mentioned earlier, Go language has built-in two concurrency features, Goroutine and Channel , which makes it very easy for back-end developers to perform asynchronous programming. Golang also has built-in

    sync
    Library , contains
    Mutex
    (Mutual exclusion lock),
    WaitGroup
    (Waiting group),
    Pool
    (Temporary Object Pool) and other interfaces to help developers more safely control the concurrent behavior of Go programs in concurrent programming. Golang also has many distributed application development tools , such as distributed storage systems (Etcd, SeaweedFS), RPC libraries (gRPC, Thrift), mainstream database SDKs (mongo-driver, gnorm, redigo), etc. These can help developers effectively build distributed applications.

    Web Crawler

    Developers who have a little knowledge of web crawlers should have heard of Scrapy, and no matter what, it is also Python. There are countless technical books about Python web crawlers in the market, such as Cui Qingcai's "Python 3 Web Development Practical Combat" and Wei Shidong's "Python 3 Web Crawler Collection: A High-performance Crawler Framework Scrapy written in Python", which has been the first choice of crawler engineers since its release. .

    However, due to the recent rapid development of the Go language, more and more crawler engineers have noticed the huge advantages of using Golang to develop web crawlers. Among them, the Colly crawler framework written in Go language has now 13k+ stars on Github. Its concise API and efficient collection speed have attracted many crawler engineers and occupy part of the share of Scrapy, one of the crawlers. As mentioned earlier, the built-in concurrency feature of the Go language makes crawlers that rely heavily on network bandwidth more efficient and greatly improves the efficiency of data collection. In addition, as a static language, Go language has better constraints than the dynamic language Python, so its robustness and stability are better.

    Backend API

    Golang has many excellent back-end frameworks, most of them fully support the various functional requirements of modern back-end systems: RESTful API, routing, middleware, configuration, authentication and other modules. Moreover, back-end applications written in Golang have high performance and usually have very fast response speeds. I used Golang to refactor the Python back-end API in the open source crawler management platform Crawlab . The response speed has been optimized from a few hundred milliseconds to tens of milliseconds or even a few milliseconds. Practice has proved that the Go language has a comprehensive back-end performance. Pressure dynamic language. The more well-known back-end frameworks in the Go language include Gin , Beego , Echo , and Iris .

    Of course, this is not to say that writing the backend in Golang is completely the right choice. The author will use Java and C# in my work. After using their respective mainstream frameworks (SpringBoot and .Net Core), I found that although the syntax of these two traditional OOP languages is verbose, their grammatical features are very rich, especially generics. Can easily deal with some logically complex and highly repetitive business requirements. Therefore, the author thinks that when considering using Go to write back-end APIs, you can investigate Java or C# in advance. They have done a great job in writing back-end business functions.

    summary

    This article starts with the main grammatical features of the Go language, and gradually analyzes the advantages and disadvantages of the Go language as a back-end programming language, as well as its trial scenarios in actual software project development. The author believes that the main difference between the Go language and other languages lies in the concise syntax , natural support for concurrency , interface-oriented programming , error handling, etc., and analyzes the pros and cons of each language feature. Finally, based on the previous analysis, the author came up with the applicable scenarios of the Go language as a back-end development programming language, that is, distributed applications , web crawlers, and back-end APIs . Of course, the actual application field of the Go language is not limited to this. In fact, many well-known databases are developed in Golang, such as time series databases Prometheus and InfluxDB, and TiDB, which is also known as NewSQL. In addition, in terms of machine learning, Go language also has certain advantages, but for now, Google seems to have not vigorously promoted the application of Go in machine learning because of the intention to cooperate with Swift and TensorFlow, but some potential open source projects have emerged. , Such as GoLearn, GoML, Gorgonia, etc.

    While understanding the advantages and applicable scenarios of the Go language, we must realize that the Go language is not omnipotent. Compared with other mainstream frameworks, it also has some disadvantages. When developers are preparing to adopt Go as the actual work development language, they need to fully understand its language features, so as to make the most reasonable technical selection. Just like playing tennis, it is not only necessary to master the forehand and backhand, but also to be able to serve the ball, high-pressure ball, volley and other technical movements, so that the tennis can be played well.

    community

    If you are interested in the author's article, you can add the author's WeChat tikazyq1 and indicate "Code of Tao", and the author will pull you into the "Code of Tao" exchange group.