📜 ⬆️ ⬇️

Why Go Design is Bad for Smart Programmers

Over the past months I have been using Go to implement Proof of Concept (free code: test the idea) in my spare time, in part to learn the programming language itself. The programs themselves are very simple and are not the goal of writing an article, but the experience of using Go deserves to say a few words about it. Go promises to be a mass language for serious scalable code. The language was created in Google, in which it is actively used. Having drawn the line, I sincerely believe that the design of the Go language is bad for smart programmers.


Created for weak programmers?


Go is very easy to learn, so simple that the introduction took me one evening, after which I could write the code productively. The book on which I studied Go is called An Introduction to Programming in Go ( translation ), it is available online. The book, like the Go source itself, is easy to read, it has good code examples, it contains about 150 pages that can be read at a time. At first, this simplicity is refreshing, especially in the world of programming, full of advanced technologies. But in the end, sooner or later the thought arises: "Is this really so?"


Google claims that the simplicity of Go is an appealing trait, and the language is designed for maximum productivity in large teams, but I doubt it. There are features that are either lacking or they are excessively detailed. And all because of the lack of confidence in the developers, with the assumption that they are not able to do something right. 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 are a couple of quotes from Rob Pike ( comment : one of the co-authors of Go):


The key point here is that our programmers are not researchers. They, as a rule, are very young, they come to us after their studies, they may have 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 their language should be easy for them to understand and learn.

He should be familiar, roughly speaking similar to C. Google programmers start their careers early and are mostly 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.

What? So Rob Pike basically says that the developers at Google are not so good, because they created a language for idiots, so that they could do something. What an arrogant look at your own colleagues? I have always believed that Google developers are selected from the brightest and best on Earth. Of course they can handle something more complicated?


Over-simplicity artifacts


Being simple is a worthy pursuit in any design, and trying to make something simple is difficult. However, when trying to solve (or even express) complex tasks, sometimes a complex tool is needed. Complexity and complexity are not the best features of a programming language, but there is a middle ground in which it is possible to create elegant abstractions in a language that are easy to understand and use.


Not very expressive


Because of the striving for simplicity, Go lacks constructions that are perceived in other languages ​​as something natural. At first, this may seem like a good idea, but in practice, verbose code comes out. The reason for this should be obvious - it is necessary that developers simply read someone else's code, but in fact these simplifications only harm readability. Abbreviations in Go are missing: either a lot or nothing.


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()
    flags := flag.Args()

    var text string
    var scanner *bufio.Scanner
    var err error

    if len(flags) > 0 {

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

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

        scanner = bufio.NewScanner(file)

    } else {
        scanner = bufio.NewScanner(os.Stdin)
    }

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

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

    fmt.Println(text)
}

, Go , .


, , D:


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);
    }
}

? D. , . D (..: ), Go, , .



Go — . . , , , :


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 int16Sum(list []int16) (uint64) {
    var result int16 = 0
    for x := 0; x < len(list); x++ {
        result += list[x]
    }
    return uint64(result)
}

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

func main() {

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

    fmt.Println(int8Sum(list8))
    fmt.Println(int16Sum(list16))
    fmt.Println(int32Sum(list32))
    fmt.Println(int64Sum(list64))
}

. (DRY), , . Go ? .


D:


import std.stdio;
import std.algorithm;

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

, . reduce . , Go, . ?



, , Go : " !". , , !


:


package main

import "fmt"
import "reflect"

func Reduce(in interface{}, memo interface{}, fn func(interface{}, interface{}) interface{}) interface{} {
    val := reflect.ValueOf(in)

    for i := 0; i < val.Len(); i++ {
        memo = fn(val.Index(i).Interface(), memo)
    }

    return memo
}

func main() {

    list := []int{1, 2, 3, 4, 5}

    result := Reduce(list, 0, func(val interface{}, memo interface{}) interface{} {
        return memo.(int) + val.(int)
    })

    fmt.Println(result)
}

Reduce Idiomatic generics in Go (..: , , ). , , . interface{} — , . , . , . . , , .


, . .

D . - , interface{} ?



Go , VCS. Go , . , ! , github bitbucket Go, . . .


, Go , , . " ". ? , Go .



- , Go , , - . (.: training wheels). , (, , ) . , .


, Go — ( ). , . , - — , .



Go , . , . . .


, .


mersinvald


')

Source: https://habr.com/ru/post/344356/


All Articles