Why Slow Thinkers Cannot Use GO Programming Languages?

GO Programming Language Main Logo

Why Slow Thinkers Cannot Use GO Programming Languages?

Go is becoming an increasingly popular language for serious scalable code. The language was created on Google, in which it is actively used. Having drawn the line, I sincerely believe that the design of the Go language is bad for non-intelligent programmers.

Created for weak programmers?

The weak talk about problems. Strong talk about ideas and dreams …

SmartSpate

Go is very easy to learn, so simple that you can read the code with little or no training at all. This feature of the language is used in many global companies when the code is read together with non-core specialists (managers, customers, etc.). This is very convenient for methodologies such as Design Driven Development.

Even novice programmers begin to issue quite a decent code after a week or two. The book on which I studied Go is called “Programming in Go” (written by Mark Summerfield). The book is very good, it affects many of the nuances of the language. After unreasonably complicated languages ​​such as Java, PHP, the lack of magic acts refreshingly. But sooner or later, many limited programmers have a desire to use the old methods in the new field. Is it really necessary?

Rob Pike (the main ideologue of the language) created the Go language, as an industrial language that is easy to understand, effective in use. The language is designed for maximum productivity in large teams and there is no doubt about it. Many novice programmers complain that there are many features that they lack. This striving for simplicity was a conscious decision of the developers of the language and, in order to fully understand why this was necessary, we must understand the motivation of the developers and what they sought in Go.

So why was it created so simple? Here is a couple of Rob Pike quotes:

  • The key point here is that our programmers are not researchers. As a rule, they are very young, they come to us after their studies, they have probably studied Java, or C/C++, or Python. They are not able to understand the outstanding language, but at the same time, we want them to create good software. That is why language should be easy to understand and learn.
  • He should be familiar, roughly speaking similar to C. Google programmers start their careers early and most of them are familiar with procedural languages, in particular, the C family. The demand for fast productivity in a new programming language means that the language should not be too radical.

Simplicity artifacts

Simplicity is a prerequisite for beauty.


Lev Tolstoy.

Being simple is one of the most important aspirations in any design. As you know, a perfect project is not a project where there is nothing to add, but one in which there is nothing to remove. Many believe that in order to solve (or even express) complex problems, a complex tool is needed. However, it is not. Take for example the language PERL. The ideologists of the language believed that the programmer should have at least three different ways to solve one problem. The ideologists of the Go language went the other way, they decided that to achieve the goal one way is enough, but really good. Such an approach has a serious foundation: the only way is easier to learn and harder to forget.

Many migrants complain that the language does not contain elegant abstractions. Yes, it is, but this is one of the main advantages of the language. The language contains in its composition a minimum of magic – therefore, deep knowledge is not required for reading the program. As for the verbosity of the code, this is not a problem at all. A well-written program in the Golang language is readable vertically, with almost no structuring. In addition, the speed of reading the program at least an order of magnitude greater than the speed of writing. If we consider that all the code has uniform formatting (done with the built-in gofmt command), then reading a few extra lines is not a problem at all.

Not very expressive

Art does not tolerate when its freedom is constrained. Accuracy is not his responsibility.

SmartSpate

Because of the desire for simplicity in Go, there are no constructions that are perceived in other languages ​​as something natural by people who are used to them. At first, this may be somewhat inconvenient, but then you notice that the program is read at times simpler and more unambiguous.

For example, a console utility that reads stdin or a file from the command line arguments will look like this:

package main

import (
    "bufio"
    "flag"
    "fmt"
    "log"
    "os"
)

func main() {

    flag.Parse()

    scanner := newScanner(flag.Args())

    var text string
    for scanner.Scan() {
        text += scanner.Text()
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }

    fmt.Println(text)
}

func newScanner(flags []string) *bufio.Scanner {
    if len(flags) == 0 {
        return bufio.NewScanner(os.Stdin)
    }

    file, err := os.Open(flags[0])

    if err != nil {
        log.Fatal(err)
    }

    return bufio.NewScanner(file)
}

The solution of the same problem in the D language, although it looks somewhat shorter, however, is not read at all easier.

import std.stdio, std.array, std.conv;

void main(string[] args)
{
    try
    {
        auto source = args.length > 1 ? File(args[1], "r") : stdin;
        auto text   = source.byLine.join.to!(string);

        writeln(text);
    }
    catch (Exception ex)
    {
        writeln(ex.msg);
    }
}

Hard to copy

The man wears hell in himself.

Martin Luther

Newbies constantly complain about Go in terms of lack of generics. To resolve this issue, most of them use direct copying code. For example, such pseudo-professionals believe that the function for summing the list of integers is that it is impossible to implement the functionality in any way other than by simple copying and pasting for each data type.

package main

import "fmt"

func int64Sum(list []int64) (uint64) {
    var result int64 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

func int32Sum(list []int32) (uint64) {
    var result int32 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

func main() {

    list32 := []int32{1, 2, 3, 4, 5}
    list64 := []int64{1, 2, 3, 4, 5}

    fmt.Println(int32Sum(list32))
    fmt.Println(int64Sum(list64))
}

There are sufficient means in the language to implement such constructions. For example, generic programming is fine.

package main

import "fmt"

func Eval32(list []int32, fn func(a, b int32)int32) int32 {
    var res int32
    for _, val := range list {
        res = fn(res, val)
    }
    return res
}

func int32Add(a, b int32) int32 {
    return a + b
}

func int32Sub(a, b int32) int32 {
    return a - b
}

func Eval64(list []int64, fn func(a, b int64)int64) int64 {
    var res int64
    for _, val := range list {
        res = fn(res, val)
    }
    return res
}

func int64Add(a, b int64) int64 {
    return a + b
}

func int64Sub(a, b int64) int64 {
    return a - b
}

func main() {

    list32 := []int32{1, 2, 3, 4, 5}
    list64 := []int64{1, 2, 3, 4, 5}

    fmt.Println(Eval32(list32, int32Add))
    fmt.Println(Eval64(list64, int64Add))
    fmt.Println(Eval64(list64, int64Sub))
}

And, although our code turned out to be somewhat longer than the previous case, it became generalized. Therefore, we will not be difficult to implement all the arithmetic operations.

Many will say that a program in D looks much shorter and will be right.

import std.stdio;
import std.algorithm;

void main(string[] args)
{
    [1, 2, 3, 4, 5].reduce!((a, b) => a + b).writeln;
}

However, only shorter, but not correct, since the implementation on D completely ignores the problem of error handling.

In real life, when the complexity of logic increases, the gap is rapidly narrowing. Even more rapidly, the gap is reduced when an action is required to be performed that cannot be performed with the help of standard language operators.

In terms of maintainability, extensibility, readability, in my opinion, the Go language wins, although it loses in wordiness.

Generalized programming in some cases gives us an undeniable benefit. This clearly illustrates the sort package. So, to sort any list, we just need to implement the interface sort. Interface.

import "sort"

type Names []string

func (ns Names) Len() int {
    return len(ns)
}

func (ns Names) Less(i, j int) bool {
    return ns[i] < ns[j]
}

func (ns Names) Swap(i, j int) {
    ns[i], ns[j] = ns[j], ns[i]
}

func main() {
    names := Names{"London", "Berlin", "Rim"}
    sort.Sort(names)
}

If you take any open source project and execute the grep “interface {}” -R command, you will see how often the user interfaces are used. Comrade comrades will immediately say that all this is due to the lack of generics. However, this is not always the case. Take for example the language DELPHI. Despite the fact that he has these same generics, it contains a special type of VARIANT for operations with arbitrary data types. The Go language does the same.

From the gun on the sparrows

And the straitjacket must match the size of the madness.

Stanislav Lec

Many extreme lovers can say that Go has another mechanism for creating generics – reflection. And they will be right … but only in rare cases.

Rob Pike warns us:

It is a powerful tool that should be used with care. It should be avoided as long as it is not strictly necessary.

Wikipedia tells us the following:

Reflection means a process during which a program can monitor and modify its own structure and behavior at run time. The programming paradigm underlying reflection is called reflexive programming. This is a type of metaprogramming.
However, as you know, you have to pay for everything. In this case, it is:

  • The complexity of writing programs
  • The program execution speed

Therefore, it is necessary to use reflection with caution, as tools of large caliber. Thoughtless use of reflection leads to unreadable programs, constant errors and low speed. Just the fact that a snob-programmer could show off his code in front of other, more pragmatic and modest colleagues.

Cultural baggage from C? No, from a number of languages!

Along with the state, heirs are also left with debts.
Despite the fact that many people believe that the language is completely based on the legacy of C, this is not the case. The language has incorporated many aspects of the best programming languages.

Syntax

First of all, the syntax of grammatical structures is based on the syntax of the C language. However, the DELPHI language also had a significant impact. So, we see that the excess brackets are completely removed, so greatly reducing the readability of the program. The language also contains the operator “: =” inherent in the DELPHI language. The concept of packages is borrowed from languages ​​like ADA. The declaration of unused entities is borrowed from the PROLOG language.

Semantics

The basis of the packages was taken the semantics of the language DELPHI. Each package encapsulates data and code and contains private and public entities. This allows the package interface to be reduced to a minimum.

The implementation of the delegation method was borrowed from the DELPHI language.

Compilation

No wonder there is a joke: Go was developed while the C program was compiled. One of the strengths of the language is super-fast compilation. The idea was borrowed from the DELPHI language. In addition, each Go package corresponds to the DELPHI module. These packages are recompiled only when really necessary. Therefore, after the next edit, it is not necessary to compile the entire program, and it is enough to recompile only the modified packages and packages that depend on these modified packages (and only then, if the package interfaces have changed).

High-level designs

The language contains many different high-level constructions that are not related to low-level C-type languages.

  • Strings
  • Hash table
  • Slices
  • Duck typing is borrowed from languages ​​like RUBY (which, unfortunately, many do not understand and do not use at full power).

Memory management

Memory management generally deserves a separate article. If in languages ​​like C ++, control is completely given to the developer, in later languages ​​like DELPHI, the reference counting model was used. With this approach, cyclic references were not allowed, since lost clusters were formed, then Go is integrated with detection of such clusters (as in C #). In addition, garbage collector surpasses most currently known implementations in performance and can already be used for many real-time tasks. The language itself recognizes situations where the value for storing a variable can be allocated on the stack. This reduces the load on the memory manager and increases the speed of the program.

Parallelism and competitiveness

The parallelism and competitiveness of language is beyond praise. No low-level language can even remotely compete with the Go language. In fairness, it is worth noting that the model was not invented by the authors of the language but simply borrowed from the good old ADA language. The language is able to handle millions of parallel connections involving all CPUs while having an order less than the typical for multi-threaded code complex problems with deadlocks and race conditions.

Additional benefits

If it is profitable, everyone will become disinterested.

SmartSpate

The language also provides us with a number of undoubted benefits:

  • The only executable file after building the project greatly simplifies the deploy application.
  • Static typing and type inference can significantly reduce the number of errors in the code, even without writing tests. I know some programmers who generally do without writing tests and at the same time, the quality of their code does not significantly suffer.
  • Very simple cross-compilation and excellent portability of the standard library, which greatly simplifies the development of cross-platform applications.
  • RE2 regular expressions are thread-safe and with predictable runtime.
  • Powerful standard library, which allows in most projects to do without third-party frameworks.
  • The language is powerful enough to concentrate on the task, and not on the methods of solving it, and at the same time low enough so that the task can be solved effectively.
  • The ecosystem Go already contains out of the box a developer toolkit for all occasions: tests, documentation, package management, powerful linters, code generation, race conditions detector, etc.
  • Go version 1.11 has built-in semantic dependency management, built on top of the popular VCS hosts. All the tools that make up the Go ecosystem use these services to download, build, and install code from them in one fell swoop. And this is great. With the advent of version 1.11, the problem with versioning packages was also completely resolved.
  • Since the main idea of ​​the language is to reduce magic, the language encourages developers to perform error handling explicitly. And rightly so, because otherwise, he will simply forget about error handling altogether. Another thing is that most developers deliberately ignore error handling, preferring instead to handle them, just to send an error up.
  • The language does not implement the classical OOP methodology since Go is no virtuality in its pure form. However, this is not a problem when using interfaces. The lack of OOP significantly reduces the entry barrier for beginners.

Simplicity for community benefits

Complicate is simple, difficult to simplify.

SmartSpate

Go was designed to be simple and he succeeded in this goal. It was written for smart programmers who understand all the advantages of teamwork and are tired of the infinite variability of Enterprise level languages. Having a relatively small set of syntactic structures in its arsenal, it is almost not subject to change over time, so developers have plenty of time freed up precisely for development, and not for endless learning of language innovations.

Companies also receive a number of advantages: a low entry threshold allows you to quickly find a specialist, and the immutability of the language allows you to use the same code 10 years later.

Conclusion

The large size of the brain has not made a single elephant the Nobel Prize.

SmartSpate

For those programmers whose personal ego prevails over team spirit, as well as theorists who love academic tasks and endless “self-improvement”, the language is really bad, because it is a general-purpose artisan language that does not allow one to get aesthetic pleasure from the result of his work a professional in front of colleagues (provided that we measure the mind with these criteria, and not with the IQ coefficient). Like everything in life – this is a matter of personal priorities. Like all upcoming innovations, the language has already come a long way from general denial to mass recognition. The language is ingenious in its simplicity, and, as you know, everything ingenious is simple!

Summary

Among all the harsh criticisms aimed at Go, the following statements stand out:

  • No generics. If we look at the statistics of the most popular languages, then we note that half of the languages ​​from the top ten do not have generics. Most generics are needed only in containers. Therefore, the gain from them is not too big.
  • Other languages ​​like Rust are much better (at least in the XXX site nominations). Again, if we look at the statistics of the most popular languages, we will not find the Rust language in the list at all or it will be somewhere below the ranking. I personally like Rust, but I chose Go.
  • The XXX language has such a bun. This is the reverse side of the simplicity coin. The disadvantage of this or not is for everyone to decide. However, the project developers gave their preference in favor of simplicity.
  • Here they will release Go 2.0, then we’ll see. This position is occupied by observers, not practices.
  • Not expressive enough. I agree that expressiveness is lame at some places, but in general, it is a simple and consistent language. In addition, due to the poverty of the language, we are forced to pay more attention to the architecture of the application being developed, which has a positive effect on its flexibility.

Actually, the article was not conceived about the syntactic merits of the Go language, but as a brief overview of its merits for teamwork and the effective evolution of the project under development. The implication was that the article would have a sequel, with reference to more specific problems. However, due to the absence of interest in the topic – there will most likely not be a continuation.

Experiment

Believe the words – neither yours nor the strangers, but trust the deeds – both yours and those of others.

SmartSpate

The final part is intended exclusively for the category of people who identify themselves as constructive-minded optimists and can confirm this with their deeds. The rest of the audience, please skip this part.

I was inspired to change this experiment by friends who claimed that all constructively thinking optimists had long since left (at least virtually) the expanses of our country and settled, for example, on Stack Overflow, and here mostly remained snobs. For a long time I did not believe them, so I decided to conduct this experiment.
On Habré several articles were posted, the result of the analysis of comments on which I cite.

  • Indeed, the hypothesis of my friends was confirmed, however, there are still adequate people among the smart spate readers, although their percentage is rapidly falling. Yury Bykov calls such people “fools” on whom the whole country rests. According to his version, their percentage is small (about 2%). I am not so pessimistic, and I think that there are many more of them.
  • The law of the media. Destructive information is much more interesting than constructive.
  • The psychology of the crowd. This is a terrible thing, it even makes an cruel sheep out of an adequate person. A person in a crowd is no longer a person. Objectivity is out of the question. No logical arguments, no authoritative sources or precedents to it are no longer valid.
  • Responsibility and impunity. People are ready to humiliate another person with pleasure in order to exalt themselves (at least in their own eyes). Especially if you don’t have to answer for that (which can be easier – you clicked a minus and you don’t even need to write a comment). There is as much in common between words and deeds as between the canal and the sewage system.
  • Vanity. Most snobs are ready to stand out in any way. They are not afraid of any moral obstacles.
  • Pessimism. Unlike Western countries (and especially America), pessimism prevails in the country. As you know, an optimist is looking for opportunities among the difficulties, and a pessimist for difficulties among the possibilities. In our country, almost no one pays attention to the positive qualities of anything.
  • Professionalism and worldview circle. Most people choose tools as an end in themselves, not as a means to an end. People have forgotten how to work with information. People do not see the trees behind the forest. From the array of information they are not able to highlight the main ideas. Nobody wants to look from another point of view that is not standard for oneself. Dissent is suppressed. Here it is not accepted.
  • Friendliness and respect. Praised friendly teams exist only in words. Values ​​of Agile development – only on paper.
  • Hypocrisy. About this you can write a separate article.
  • Principle There are people who ask the right question: “What the hell am I doing?”, But not everyone understands that because of lack of principle for us, momentary selfish interest is more important than all our principles put together. It is easiest to blame everything on circumstances and say that nothing depends on us.