Wêrom Go min is foar ûnsmart programmeurs

It artikel is skreaun as in reaksje op in earder publisearre antipodean artikel.

Wêrom Go min is foar ûnsmart programmeurs

Yn 'e ôfrûne twa plus jierren haw ik Go brûkt om in spesjalisearre RADIUS-tsjinner te ymplementearjen mei in ûntwikkele billingsysteem. Underweis lear ik de nuverheden fan de taal sels. De programma's sels binne heul ienfâldich en binne net it doel fan dit artikel, mar de ûnderfining fan it brûken fan Go sels fertsjinnet in pear wurden yn har ferdigening. Go wurdt in hieltyd mear mainstream taal foar serieuze, skalbere koade. De taal is makke troch Google, wêr't it aktyf brûkt wurdt. Bottom line, ik tink earlik sein dat it ûntwerp fan 'e Go-taal min is foar UNintelligente programmeurs.

Untworpen foar swakke programmeurs?

De swakken sprekke fan problemen. De sterke praat oer ideeën en dreamen ...

Go is heul maklik te learen, sa maklik dat jo de koade kinne lêze mei praktysk gjin training. Dizze eigenskip fan 'e taal wurdt brûkt yn in protte globale bedriuwen, as de koade wurdt lêzen tegearre mei net-kearn spesjalisten (managers, klanten, ensfh). Dit is heul handich foar metodologyen lykas Design Driven Development.
Sels begjinnende programmeurs begjinne frij fatsoenlike koade te produsearjen nei in wike as twa. It boek wêrfan ik studearre is "Go Programming" (troch Mark Summerfield). It boek is tige goed, it rekket in protte nuânses fan de taal oan. Nei ûnnedich yngewikkelde talen lykas Java, PHP, is it gebrek oan magy verfrissend. Mar ier of letter hawwe in protte beheinde programmeurs it idee om âlde metoaden yn in nij fjild te brûken. Is dit echt nedich?

Rob Pike (de wichtichste ideolooch fan 'e taal) makke de Go-taal as in yndustriële taal dy't maklik te begripen en effektyf te brûken is. De taal is ûntwurpen foar maksimale produktiviteit yn grutte teams en der is gjin twifel oer. In protte begjinnende programmeurs kleie dat d'r in protte funksjes binne dy't se misse. Dizze winsk foar ienfâld wie in bewuste beslút troch de ûntwerpers fan 'e taal, en om folslein te begripen wêrom't it nedich wie, moatte wy de motivaasje fan 'e ûntwikkelders begripe en wat se besochten te berikken yn Go.

Dus wêrom waard it sa ienfâldich makke? Hjir binne in pear sitaten fan Rob Pike:

It wichtichste punt hjir is dat ús programmeurs gjin ûndersikers binne. Se binne, as regel, frij jong, komme nei ús stúdzje, miskien se studearre Java, of C/C++, of Python. Se kinne gjin geweldige taal ferstean, mar tagelyk wolle wy dat se goede software meitsje. Dêrom moat de taal maklik te begripen en te learen wêze.

Hy soe fertroud wêze moatte, rûchwei fergelykber mei C. Programmeurs dy't wurkje by Google begjinne har karriêre betiid en binne meast bekend mei prosedurele talen, benammen de C-famylje. De eask foar flugge produktiviteit yn in nije programmeartaal betsjut dat de taal net te radikaal wêze moat.

Wize wurden, net?

Artefakten fan ienfâld

Ienfâld is in needsaaklike betingst foar skientme. Lev Tolstoj.

It ienfâldich hâlde is ien fan 'e wichtichste doelen yn elk ûntwerp. Sa't jo witte, is in perfekt projekt net in projekt wêr't neat oan te foegjen is, mar ien wêrfan neat te ferwiderjen is. In protte minsken leauwe dat om komplekse problemen op te lossen (of sels ekspresje) in kompleks ark nedich is. It is lykwols net. Litte wy bygelyks de PERL-taal nimme. Taalideologen leauden dat in programmeur op syn minst trije ferskillende manieren moat hawwe om ien probleem op te lossen. De ideologen fan 'e Go-taal namen in oare wei, se besletten dat ien manier, mar in echt goede, genôch wie om it doel te berikken. Dizze oanpak hat in serieuze basis: de ienige manier is makliker om te learen en dreger te ferjitten.

In protte migranten kleie dat de taal gjin elegante abstraksjes befettet. Ja, dit is wier, mar dit is ien fan 'e wichtichste foardielen fan' e taal. De taal befettet in minimum fan magy - dus gjin djippe kennis is nedich om it programma te lêzen. Wat de verbosity fan 'e koade oanbelanget, is dit hielendal gjin probleem. In goed skreaun Golang-programma lêst fertikaal, mei in bytsje of gjin struktuer. Derneist is de snelheid fan it lêzen fan in programma op syn minst in folchoarder fan grutte grutter as de snelheid fan it skriuwen. As jo ​​beskôgje dat alle koade unifoarme opmaak hat (dien mei it ynboude gofmt-kommando), dan is it lêzen fan in pear ekstra rigels hielendal gjin probleem.

Net hiel ekspressyf

Keunst tolerearret net as har frijheid beheind wurdt. Krektens is net syn ferantwurdlikens.

Fanwege de winsk nei ienfâld mist Go konstruksjes dy't yn oare talen wurde ûnderfûn as wat natuerlik troch minsken dy't har wend binne. Earst kin it wat ûngemaklik wêze, mar dan fernimme jo dat it programma folle makliker en dúdliker te lêzen is.

Bygelyks, in konsole-hulpprogramma dat stdin lêst as in bestân fan kommandorigelarguminten soe der sa útsjen:

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

De oplossing foar itselde probleem yn D, hoewol it wat koarter liket, is net makliker te lêzen

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

Hel fan kopiearjen

De minske draacht de hel yn himsels. Martin Luther.

Begjinners kleie konstant oer Go yn termen fan it gebrek oan generika. Om dit probleem op te lossen, brûke de measten fan har direkte koade kopiearje. Bygelyks, in funksje foar it opteljen fan in list fan hiele getallen, sokke soe-wêze professionals leauwe dat de funksjonaliteit net op in oare manier ymplementearre wurde kin as troch ienfâldige kopiearje-plakken foar elk gegevenstype.

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

De taal hat genôch middels om sokke konstruksjes út te fieren. Bygelyks, generike programmearring soe goed wêze.

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

En hoewol ús koade wat langer die bliken te wêzen as it foarige gefal, is it generalisearre wurden. Dêrom sil it net dreech wêze foar ús om alle rekenkundige operaasjes út te fieren.

In protte sille sizze dat in programma yn D liket folle koarter, en se sille wêze gelyk.

import std.stdio;
import std.algorithm;

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

It is lykwols allinich koarter, mar net krekter, om't de D-ymplemintaasje it probleem fan flaterôfhanneling folslein negeart.

Yn it echte libben, as de kompleksiteit fan logika tanimt, wurdt it gat rap smel. It gat slút noch rapper as jo in aksje útfiere moatte dy't net útfierd wurde kin mei standerttaaloperators.

Wat ûnderhâldberens, útbreidberens en lêsberens oanbelanget, wint neffens my de Go-taal, al ferliest er oan verbosity.

Generalisearre programmearring jout ús yn guon gefallen ûnbestride foardielen. Dit wurdt dúdlik yllustrearre troch it sortepakket. Dus, om elke list te sortearjen, moatte wy gewoan de sort.Interface-ynterface ymplementearje.

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

As jo ​​in iepen boarne-projekt nimme en it kommando grep "ynterface{}" -R útfiere, sille jo sjen hoe faak betiizjende ynterfaces wurde brûkt. Close-minded kameraden sille fuortendaliks sizze dat dit alles komt troch it gebrek oan generika. Dit is lykwols net altyd it gefal. Litte wy DELPHI as foarbyld nimme. Nettsjinsteande de oanwêzigens fan deselde generika, befettet it in spesjale VARIANT-type foar operaasjes mei willekeurige gegevenstypen. De Go-taal docht itselde.

Fan in kanon oant sparrows

En it dwersjacke moat passe by de grutte fan 'e waansin. Stanislav Lec.

In protte ekstreme fans kinne beweare dat Go in oar meganisme hat foar it meitsjen fan generika - refleksje. En se sille gelyk wêze ... mar allinich yn seldsume gefallen.

Rob Pike warskôget ús:

Dit is in krêftich ark dat mei foarsichtigens brûkt wurde moat. It moat foarkommen wurde, útsein as strikt nedich.

Wikipedia fertelt ús it folgjende:

Refleksje ferwiist nei it proses wêryn't in programma syn eigen struktuer en gedrach by de útfiering kontrolearje en wizigje kin. It programmearringparadigma dat ûnderlizzende refleksje wurdt neamd reflektyf programmearring. Dit is in soarte fan metaprogrammearring.

Lykwols, lykas jo witte, moatte jo foar alles betelje. Yn dit gefal is it:

  • muoite mei it skriuwen fan programma's
  • programma útfier snelheid

Dêrom moat refleksje mei foarsichtigens brûkt wurde, lykas in grut kaliber wapen. Untachteleas gebrûk fan refleksje liedt ta ûnlêsbere programma's, konstante flaters en lege snelheid. Krekt it ding foar in snobprogrammeur om syn koade sjen litte te kinnen foar oare, mear pragmatyske en beskieden kollega's.

Kulturele bagaazje út Xi? Nee, út in tal talen!

Tegearre mei it fortún wurde ek skulden neilitten oan de erfgenamten.

Nettsjinsteande it feit dat in protte leauwe dat de taal folslein basearre is op it C-erfgoed, is dat net it gefal. De taal omfettet in protte aspekten fan 'e bêste programmeartalen.

syntaksis

Alderearst is de syntaksis fan grammatikale struktueren basearre op de syntaksis fan 'e C-taal. De DELPHI-taal hie lykwols ek in wichtige ynfloed. Sa sjogge wy dat de oerstallige haakjes, dy't de lêsberens fan it programma gâns ferminderje, folslein fuorthelle binne. De taal befettet ek de operator ":=" dy't ynherint is oan 'e DELPHI-taal. It konsept fan pakketten is liend fan talen lykas ADA. De ferklearring fan net brûkte entiteiten is liend fan 'e PROLOG-taal.

Semantyk

De pakketten wiene basearre op de semantyk fan 'e DELPHI-taal. Elk pakket omfettet gegevens en koade en befettet partikuliere en publike entiteiten. Hjirmei kinne jo de pakketynterface oant in minimum ferminderje.

De metoade foar ymplemintaasje troch delegaasje waard liend fan 'e DELPHI-taal.

Kompilaasje

It is net sûnder reden dat der in grap is: Go waard ûntwikkele wylst in C-programma waard gearstald. Ien fan 'e sterke punten fan' e taal is har ultrasnelle kompilaasje. It idee waard liend fan 'e DELPHI-taal. Elk Go-pakket komt oerien mei in DELPHI-module. Dizze pakketten wurde allinich opnij kompilearre as it echt nedich is. Dêrom hoege jo nei de folgjende bewurking net it hiele programma te kompilearjen, mar leaver allinich de feroare pakketten en pakketten opnij kompilearje dy't ôfhinklik binne fan dizze feroare pakketten (en sels dan allinich as de pakketynterfaces binne feroare).

Konstruksjes op hege nivo

De taal befettet in protte ferskillende konstruksjes op heech nivo dy't op gjin inkelde manier besibbe binne oan talen op leech nivo lykas C.

  • Strings
  • Hash tabellen
  • Slices
  • Ducktyping wurdt liend út talen lykas RUBY (dy't, spitigernôch, in protte net begripe of har folsleine potensjeel brûke).

Unthâld behear

Unthâldbehear fertsjinnet algemien in apart artikel. As yn talen lykas C++ de kontrôle folslein oerlitten wurdt oan de ûntwikkelder, dan waard yn lettere talen lykas DELPHI in referinsjetelmodel brûkt. Mei dizze oanpak wiene cyclyske referinsjes net tastien, om't weesklusters waarden foarme, dan hat Go ynboude deteksje fan sokke klusters (lykas C #). Derneist is de garbage collector effisjinter dan de measte op it stuit bekende ymplemintaasjes en kin al brûkt wurde foar in protte real-time taken. De taal sels herkent situaasjes as in wearde foar it bewarjen fan in fariabele kin wurde tawiisd oan 'e stapel. Dit ferleget de lading op 'e ûnthâld manager en fergruttet de snelheid fan it programma.

Tagelyk en gearfal

It parallelisme en konkurrinsjefermogen fan 'e taal is boppe lof. Gjin taal op leech nivo kin sels op ôfstân konkurrearje mei Go. Om earlik te wêzen, is it de muoite wurdich op te merken dat it model net útfûn waard troch de skriuwers fan 'e taal, mar gewoan liend út' e goede âlde ADA-taal. De taal is by steat om te ferwurkjen miljoenen parallelle ferbinings mei help fan alle CPUs, wylst it hawwen fan in folchoarder fan grutte minder komplekse problemen mei deadlocks en race betingsten dy't typysk binne foar multi-threaded koade.

Oanfoljende foardielen

As it rendabel is, sil elkenien selsleas wurde.

Taal biedt ús ek in oantal ûnbestriden foardielen:

  • In inkele útfierbere triem nei it bouwen fan it projekt simplifies de ynset fan applikaasjes gâns.
  • Statysk typen en type konklúzje kinne it oantal flaters yn jo koade signifikant ferminderje, sels sûnder tests te skriuwen. Ik ken guon programmeurs dy't hielendal sûnder it skriuwen fan tests dogge en de kwaliteit fan har koade hat net signifikant te lijen.
  • Hiel ienfâldige cross-kompilaasje en poerbêste portabiliteit fan de standert bibleteek, dy't gâns simplifies de ûntwikkeling fan cross-platform applikaasjes.
  • RE2 reguliere útdrukkingen binne thread-feilich en hawwe foarsisbere útfieringstiden.
  • In krêftige standertbibleteek wêrmei de measte projekten kinne dwaan sûnder ramt fan tredden.
  • De taal is machtich genôch om te rjochtsjen op it probleem yn stee fan hoe't it op te lossen, mar leech nivo genôch dat it probleem kin wurde oplost effisjint.
  • It Go eco-systeem befettet al ûntwikkele ark út 'e doaze foar alle gelegenheden: tests, dokumintaasje, pakketbehear, krêftige linters, koadegeneraasje, detektor foar racebetingsten, ensfh.
  • Go ferzje 1.11 yntrodusearre ynboude semantysk ôfhinklikensbehear, boud boppe op populêre VCS-hosting. Alle ark dy't it Go-ekosysteem foarmje, brûke dizze tsjinsten om koade fan har te downloaden, te bouwen en te ynstallearjen yn ien klap. En dat is geweldich. Mei de komst fan ferzje 1.11 waard it probleem mei pakketferzje ek folslein oplost.
  • Om't it kearnidee fan 'e taal is om magy te ferminderjen, stimulearret de taal ûntwikkelders om flaterôfhanneling eksplisyt te dwaan. En dit is korrekt, om't oars, it sil gewoan ferjitte oer flater ôfhanneling hielendal. In oar ding is dat de measte ûntwikkelders flaterôfhanneling bewust negearje, en leaver ynstee fan har te ferwurkjen om de flater gewoan nei boppen troch te stjoeren.
  • De taal ymplementearret de klassike OOP-metodology net, om't yn syn suvere foarm gjin virtualiteit yn Go is. Dit is lykwols gjin probleem by it brûken fan ynterfaces. It ûntbrekken fan OOP fermindert de yntreebarriêre foar begjinners signifikant.

Ienfâld foar mienskip foardiel

It is maklik te komplisearjen, dreech te ferienfâldigjen.

Go is ûntwurpen om ienfâldich te wêzen en it slagget op dat doel. It is skreaun foar tûke programmeurs dy't de foardielen fan teamwurk begripe en wurch binne fan 'e einleaze fariabiliteit fan talen op Enterprise-nivo. Mei in relatyf lytse set fan syntaktyske struktueren yn har arsenal, is it praktysk net ûnderwurpen oan feroaringen yn 'e rin fan' e tiid, sadat ûntwikkelders in protte tiid hawwe frijmakke foar ûntwikkeling, en net foar einleaze stúdzje fan taalynnovaasjes.

Bedriuwen krije ek in oantal foardielen: in lege yngongsbarriêre lit se fluch in spesjalist fine, en de ûnferoarlikens fan 'e taal kinne se sels nei 10 jier deselde koade brûke.

konklúzje

Grutte harsensgrutte hat nea in oaljefant in Nobelpriiswinner makke.

Foar dy programmeurs waans persoanlike ego foarrang hat boppe teamgeast, lykas teoretici dy't fan akademyske útdagings en einleaze "selsferbettering" hâlde, is de taal echt min, om't it in algemiene ambachtlike taal is dy't jo net tastean te krijen estetyske wille út it resultaat fan jo wurk en lit josels profesjoneel foar kollega's (mits wy mjitte yntelliginsje troch dizze kritearia, en net troch IQ). Lykas alles yn it libben is it in kwestje fan persoanlike prioriteiten. Lykas alle weardefolle ynnovaasjes is de taal al in lange wei kommen fan universele ûntkenning nei massale akseptaasje. De taal is geniaal yn syn ienfâld, en, lykas jo witte, is alles yngenieur ienfâldich!

Boarne: www.habr.com

Add a comment