Napa Desain Go Apik kanggo Programer Cerdas

Ing sasi kepungkur aku wis nggunakake Go kanggo implementasine. Bukti Konsep (kira-kira.: kode kanggo nyoba fungsi saka idea) ing wektu luang, sebagΓ©yan kanggo sinau basa program dhewe. Program kasebut gampang banget lan dudu tujuane artikel iki, nanging pengalaman nggunakake Go dhewe pantes sawetara tembung babagan iki. Ojo lali janji(kira-kira.: artikel sing ditulis ing 2015) basa populer kanggo kode skalabel serius. Basa kasebut digawe dening Google, sing digunakake kanthi aktif. Ing ngisor iki, sajujure aku mikir yen desain basa Go ora becik kanggo programer sing pinter.

Dirancang kanggo programer sing lemah?

Go iku gampang banget kanggo sinau, supaya gampang sing introduksi njupuk kula siji sore, sawise aku wis bisa kode produktif. Buku sing aku biyen sinau Go diarani Pengantar Pemrograman ing Go (jarwan), kasedhiya online. Buku kasebut, kaya kode sumber Go dhewe, gampang diwaca, duwe conto kode sing apik, lan ngemot udakara 150 kaca sing bisa diwaca sajrone lungguh. Kesederhanaan iki nyegerake ing wiwitan, utamane ing jagad pemrograman sing kebak teknologi sing rumit banget. Nanging ing pungkasan, cepet utawa mengko muncul pikiran: "Apa iki pancene?"

Google ngaku kesederhanaan Go minangka titik sade lan basa kasebut dirancang kanggo produktivitas maksimal ing tim gedhe, nanging aku ragu. Ana fitur sing ilang utawa rinci banget. Lan kabeh amarga kurang percaya marang pangembang, kanthi anggepan yen dheweke ora bisa nindakake apa-apa kanthi bener. Kepinginan kanggo kesederhanaan iki minangka keputusan sing disadari dening para perancang basa, lan supaya bisa ngerti sebabe dibutuhake, kita kudu ngerti motivasi para pangembang lan apa sing diupayakake ing Go.

Dadi kenapa digawe gampang banget? Kene sawetara kuotasi Rob Pike (kira-kira.: salah sawijining pencipta basa Go):

Titik utama ing kene yaiku programer kita (kira-kira.: Googlers) dudu peneliti. Padha, minangka aturan, cukup enom, teka kanggo kita sawise sinau, mbok menawa padha sinau Jawa, utawa C / C ++, utawa Python. Dheweke ora ngerti basa sing apik, nanging ing wektu sing padha kita pengin nggawe piranti lunak sing apik. Mula basane kudu gampang dimangerteni lan disinaoni.
 
Dheweke kudu akrab, kira-kira padha karo C. Programer sing kerja ing Google miwiti karir luwih awal lan biasane ngerti basa prosedural, utamane kulawarga C. Syarat kanggo produktivitas cepet ing basa pamrograman anyar tegese basa kasebut ora radikal banget.

opo? Dadi Rob Pike sejatine ujar manawa pangembang ing Google ora apik, mula dheweke nggawe basa kanggo wong bodho (kira-kira.: dumbed mudhun) supaya padha bisa nindakake soko. Apa jenis arrogant katon ing kolega dhewe? Aku mesthi percaya yen pangembang Google dipilih kanthi tangan saka sing paling padhang lan paling apik ing Bumi. Mesthine dheweke bisa ngatasi sing luwih angel?

Artefak kesederhanaan sing berlebihan

Dadi prasaja minangka tujuan sing pantes ing desain apa wae, lan nyoba nggawe sing prasaja iku angel. Nanging, nalika nyoba kanggo ngatasi (utawa malah nyebut) masalah Komplek, kadhangkala alat Komplek dibutuhake. Kompleksitas lan kerumitan dudu fitur paling apik saka basa pamrograman, nanging ana titik tengah ing ngendi basa kasebut bisa nggawe abstraksi elegan sing gampang dingerteni lan digunakake.

Ora ekspresif banget

Amarga prasetya kanggo kesederhanaan, Go ora duwe konstruksi sing dianggep alami ing basa liya. Iki bisa uga katon kaya ide sing apik ing wiwitan, nanging ing praktik kasebut nyebabake kode verbose. Alesan kanggo iki kudu jelas - kudu gampang kanggo pangembang maca kode wong liya, nanging nyatane simplifikasi kasebut mung ngrusak maca. Ora ana singkatan ing Go: akeh utawa ora ana.

Contone, sarana console sing maca stdin utawa file saka argumen baris perintah bakal katon kaya iki:

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

Senajan kode iki uga nyoba dadi umum sabisa, verbosity dipeksa Go ing dalan, lan minangka asil, mecahaken masalah prasaja asil ing jumlah gedhe saka kode.

Kene, contone, solusi kanggo masalah padha ing 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);
    }
}

Lan sapa sing luwih bisa diwaca saiki? Aku bakal menehi swara kanggo D. Kode dheweke luwih gampang diwaca amarga dheweke nggambarake tumindak kanthi luwih jelas. D nggunakake konsep sing luwih kompleks (kira-kira.: telpon fungsi alternatif ΠΈ pola) tinimbang ing conto Go, nanging ora ana sing rumit babagan ngerti.

Neraka salinan

Saran populer kanggo nambah Go yaiku umum. Iki paling ora bakal mbantu supaya ora nyalin kode sing ora perlu kanggo ndhukung kabeh jinis data. Contone, fungsi kanggo nyimpulake dhaptar integer ora bisa diimplementasikake kanthi cara liya saka nyalin-paste fungsi dhasar kanggo saben jinis integer; ora ana cara liya:

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

Lan conto iki ora bisa digunakake kanggo jinis sing ditandatangani. Pendekatan iki pancen nglanggar prinsip ora mbaleni dhewe (garing), salah siji saka prinsip paling misuwur lan ketok, nglirwakake kang sumber akeh kasalahan. Kenapa Go nindakake iki? Iki minangka aspek basa sing nggegirisi.

Tuladha ing D:

import std.stdio;
import std.algorithm;

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

Prasaja, elegan lan langsung menyang titik. Fungsi sing digunakake ing kene yaiku reduce kanggo jinis template lan predikat. Ya, iki maneh luwih rumit tinimbang versi Go, nanging ora angel dimangerteni dening programer pinter. Conto endi sing luwih gampang dijaga lan luwih gampang diwaca?

Bypass sistem tipe prasaja

Aku mbayangno programer Go maca iki bakal umpluk ing tutuk lan njerit, "Sampeyan nindakake iku salah!" Ya, ana cara liya kanggo nggawe fungsi lan jinis umum, nanging bisa ngilangi sistem jinis kasebut!

Deleng conto iki kanggo ndandani basa bodho kanggo ngatasi masalah kasebut:

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

implementasine iki Reduce dipinjam saka artikel kasebut Generik Idiomatik ing Go (kira-kira.: Aku ora bisa nemokake terjemahan, aku bakal bungah yen sampeyan mbantu karo iki). Nah, yen idiomatik, aku ora seneng ndeleng conto non-idiomatic. Panggunaan interface{} - farce, lan ing basa iku mung perlu kanggo pass typing. Iki minangka antarmuka kosong lan kabeh jinis ngleksanakake, ngidini kebebasan lengkap kanggo kabeh wong. Gaya pemrograman iki elek banget, lan ora mung kuwi. Prestasi akrobat kaya iki mbutuhake panggunaan refleksi runtime. Malah Rob Pike ora seneng karo wong sing nyiksa iki, kaya sing kasebut ing salah sawijining laporan.

Iki minangka alat sing kuat sing kudu digunakake kanthi ati-ati. Sampeyan kudu nyingkiri kajaba strictly perlu.

Aku bakal njupuk template D tinimbang omong kosong iki. Kepiye wong bisa ngomong interface{} luwih bisa diwaca utawa malah ngetik aman?

Kacilakan Manajemen Ketergantungan

Go duwe sistem dependensi sing dibangun ing ndhuwur panyedhiya hosting populer VCS. Piranti sing kasedhiya karo Go ngerti babagan layanan kasebut lan bisa ngundhuh, mbangun, lan nginstal kode saka wong-wong mau kanthi cepet. Nalika iki apik, ana cacat utama karo versi! Ya, bener yen sampeyan bisa entuk kode sumber saka layanan kaya github utawa bitbucket nggunakake alat Go, nanging sampeyan ora bisa nemtokake versi kasebut. Lan maneh kesederhanaan kanthi biaya migunani. Aku ora bisa ngerti logika keputusan kasebut.

Sawise takon babagan solusi kanggo masalah iki, tim pangembangan Go nggawe thread forum, kang mbatesi carane padha arep kanggo njaluk watara masalah iki. Rekomendasi kasebut mung nyalin kabeh repositori menyang proyek sampeyan sedina lan ninggalake "kaya." Apa neraka sing padha mikir? Kita duwe sistem kontrol versi sing apik banget kanthi menehi tag lan dhukungan versi sing ora digatekake para pangripta Go lan mung nyalin kode sumber.

Bagasi budaya saka Xi

Miturut pendapatku, Go dikembangake dening wong sing wis nggunakake C sajrone urip lan wong sing ora pengin nyoba sing anyar. Basa kasebut bisa diterangake minangka C kanthi roda tambahan (orig.: gembong latihan). Ora ana gagasan anyar, kajaba dhukungan kanggo paralelisme (sing, kanthi cara, apik banget) lan iki isin. Sampeyan duwe paralelisme sing apik banget ing basa sing ora bisa digunakake lan pincang.

Masalah creaking liyane yaiku Go minangka basa prosedural (kaya medeni bisu C). Sampeyan mungkasi nulis kode kanthi gaya prosedural sing krasa kuno lan ketinggalan jaman. Aku ngerti pemrograman berorientasi obyek dudu peluru perak, nanging luwih apik yen bisa abstrak rincian menyang jinis lan nyedhiyakake enkapsulasi.

Kesederhanaan kanggo entuk manfaat dhewe

Go dirancang kanthi prasaja lan sukses ing tujuan kasebut. Iki ditulis kanggo programer sing ringkih, nggunakake basa lawas minangka cithakan. Nerangake lengkap karo alat prasaja kanggo nindakake samubarang prasaja. Gampang diwaca lan gampang digunakake.

Iku banget verbose, unimpressive, lan ala kanggo programer pinter.

Бпасибо mersinvald kanggo suntingan

Source: www.habr.com

Add a comment