This column comprehensively interprets relevant knowledge in the software field, with a bias towards technical in-depth content. It mainly covers programming languages, system architecture, open source frameworks, technical management, etc. It is divided into multiple topics, each of which A topic contains multiple articles.
This article is the first article in the column, and also the first article in the GO language series. Today I would like to share my general impression of the GO language from all aspects. Subsequent articles will introduce in depth various features and programming techniques. .
Introduction
Historically, the authors of the Go language are Robert Griesemer, Rob Pike and Ken Thompson. Among them, Ken Thompson is known to programmers for his huge contributions to UNIX and C language development. Familiar. What software is written in Go so far? Container software Docker, basic software ETCD and Kubernetes, database software TiDB and InfluxDB, messaging system NSQ, and caching component GroupCache.
It can be seen that in almost every field of infrastructure software, new software written in Go language has emerged, and the market share of these software continues to rise. In addition to being a language for infrastructure software, Go language has more and more opportunities as a universal server-side language. Some development trends can also be seen from the popularity of Go language web frameworks such as Beego and Gorilla.
Sample program
Let’s take a look at GO’s coding style through a simple sample program:
Package main
import "fmt"
func main(){
Let’s take a look at the advantages and disadvantages of compiled languages. Due to the existence of the pre-compilation process, the code can be optimized and only needs to be compiled once. The runtime efficiency will be higher and it can be independent of the language environment. Run, the disadvantage is that the entire modified module needs to be compiled.
Compared with compiled languages, interpreted languages will only translate line by line when running the program. So what is linking? To be precise, linking and loading, that is, performing these two steps after compilation, so that the program can run in memory. Linking is completed through a connector, which links multiple target files into a complete, loadable, and executable target file. The entire process includes symbol resolution (associating the application symbols in the target file with the corresponding definition). two steps) and associating symbol definitions with memory locations.
Naming convention
The names of functions, constants, variables, types, statements, labels, and packages in the GO language have relatively uniform naming rules. The names start with a letter or an underscore, followed by It can be any number of characters, numbers or underscores. Note that the GO language is case-sensitive and keywords cannot be used as names. When encountering names consisting of words, GO programmers generally use the "camel case" style.
Speaking of this, let’s take a look at Java’s naming convention. Taking $ as an example, Oracle’s official website recommends not to use $ or _ to start your variable names, and it is recommended not to use the “$” character at all in naming. The original text is “The convention, however, is to always begin your variable names with a letter, not '$' or '_'". Regarding this article, Tencent has the same view. Baidu believes that although class names can support the use of the "$" symbol, it is only used in system generation (such as anonymous classes, proxy classes), and encoding cannot be used.
This type of problem has been raised by many people on StackOverFlow. The mainstream opinion is that you don’t need to pay too much attention. You only need to pay attention to whether the original code exists "_". If it exists, keep it. If it does not exist, try to keep it. Avoid use. Someone also suggested that the reason why "_" should not be used as much as possible is that low-resolution displays make it difficult for the naked eye to distinguish between "_" (one underline) and "__" (two underlines).
I personally think it may be due to the coding standards of C language. Because in C language, the macro names, variable names, and internal function names in the system header files begin with _, so when you #include the system header files, the names in these files are defined. If they match the names you use Conflicts may cause various strange phenomena. Based on various information, it is recommended not to use "_", "$", or spaces as the beginning of the name, so as not to be difficult to read or cause strange problems.
Regarding class names, the suggestion given by Russian Java expert Yegor Bugayenko is to try to use the abstraction of real-life entities. If the name of the class ends with "-er", this is not a recommended naming method. He pointed out that there is an exception to this article, and that is tool classes, such as StringUtils, FileUtils, and IOUtils. For interface names, don't use IRecord, IfaceEmployee, RedcordInterface, instead use real world entity naming.
Of course, the above are all for Java and have nothing to do with GO. The GO language is more influenced by the C language.
Variable overview
GO language includes four main declaration methods: variable (var), constant (const), type (type) and function (func). Let’s talk about some feelings related to variables:
1. The var declaration creates a variable of a specific type, then attaches a name to it, and sets its initial value. Each declaration has a common form. :var name type = expression. One more thing, the Go language allows empty strings and will not report a null pointer error.
2. You can use name:=expression to declare variables. Note: = means declaration and = means assignment.
If the life of a variable is var x int, the expression &x (address of x) obtains a pointer to an integer variable, and its type is an integer pointer (*int). If the value is called p, we can say that p points to x, or that p contains the address of x. The variable pointed to by p is written *p. The expression *p gets the value of a variable (in this case, an integer). Because *p represents a scalar, it can also appear on the left side of the assignment operator and is used to update the value of the variable.
x:=1
p:=&x//p is an integer pointer, pointing to x
fmt.Println(*p)//Output "1"
Garbage CollectionFor high-level language garbage collectors, how to know whether a variable should be recycled? The basic idea is each package-level variable, and each local variable of the currently executing function , can be used as the source of tracing the path of variables, which can be found through pointers and other means of reference. If the variable's path does not exist, then the scalar becomes inaccessible, so it does not affect any other calculations. Because the lifetime of a variable is determined by whether it is reachable, a local variable can continue to exist beyond one iteration of the loop that contains it. The design goal of the garbage collector in the GO language is a non-blocking collector. GO1.5 achieves recycling within 10 milliseconds (note that according to experiments, this statement can only be made when the GC has enough CPU time. can only be established under certain circumstances). From a design principle point of view, Go's recycler is a concurrent, three-color, mark-and-clear recycler. Its design idea was proposed by Dijkstra in 1978. The goal is to be consistent with the properties of modern hardware and modern software. Low latency needs are a perfect match. SummaryTo sum up, every new language appears for a reason, generally speaking there are two main reasons:
1. Complex scenarios or specific problems have emerged that cannot be solved by current mainstream languages;
2. A more cost-effective language is needed.
I think, except for Bell Labs, which will do something completely out of personal feelings, no company will casually lay out new technologies with no way out. As Rob Pike said, "Complexity grows in a multiplicative manner." In order to solve a certain problem, making a certain part of the system more complex little by little inevitably adds complexity to other parts.
Under the constant pressure to add system features, options and configurations, and to release quickly, simplicity is often overlooked. Achieving simplicity requires condensing the essence of the idea at the beginning of the project and developing more specific guidelines throughout the life of the project to discern which changes are good and which are bad or fatal.
With enough effort, good changes can achieve their goals without compromising what Fred Brooks called the "conceptual integrity" of software design. Bad changes don't do this, and fatal changes sacrifice simplicity for convenience. But only through simplicity in design can a system remain stable, secure, and self-consistent as it grows. The Go language not only includes the language itself and its tools and standard libraries, but also maintains a behavioral culture of extreme simplicity.