Набор ворчливых жалоб на GoLang, основанный на моих тридцати с лишним годах работы программистом. Первая часть касается кортежей или, скорее, их отсутствия.

Люди, которые хорошо меня знают, в курсе, что последние несколько лет я использую GoLang в качестве основного языка программирования. Я писал об этом в 2021 году.

«Почему я пишу GoLang в 2021 году? Он делает то, что мне нужно для продуктивной работы | Середина"

Несколько проектов, которые я прототипировал в Go, впоследствии стали успешными компонентами крупных коммерческих систем. К сожалению, хотя я и программирую на работе, с годами количество часов программирования сократилось, больше архитектуры и дизайна, чем прямых рук на клавиатуре. Это изменилось за последний месяц, когда я сосредоточился на проверке концепции нового продукта, который мы создаем.

После успешной установки Go на моем рабочем компьютере, что немаловажно, если вы работаете на предприятии за брандмауэрами и с заблокированными рабочими столами, я был готов к программированию. Этот блог кристаллизует мой нынешний почти тридцатилетний опыт профессионального разработчика. Обычно я люблю программировать на Go, но бывают моменты, когда я поднимаю руки вверх.

Где мои кортежи?

Что вы имеете в виду, говоря, что у go есть кортежи в качестве возвращаемых типов? На самом деле это не так. У него есть псевдокортежи, которые они могут использовать только в очень специфических обстоятельствах специального назначения, и даже сопоставление с образцом очень ограничено.

Почему функция не определяется как (кортеж) -> (кортеж), это позволяет создавать естественные цепочки выражений и во многих случаях устраняет необходимость в специальной обработке ошибок. Представьте, что вы могли бы написать

func f( ) (int,error) {}
func g(int, error) (int,error) {}
i, error := G( f() ) 

Вместо

i, err := f()
j, err:= g( I, err )

Or

func h( x (int,error), s string) string

Вы могли бы написать

s := h( f(), “hello”)

Затем расширение

x := f(g())

где x — кортеж (int, error), тогда

i, err := x 

Становится действительным. С «настоящими» кортежами также исчезают многие случаи, когда сегодня вам нужна небольшая структура. Если сопровождающие go не хотят добавлять в язык новую конструкцию, даже если она уже существует в рудиментарной форме, то добавление операций с индексами в struct почти то же самое.

type struct foo {
    a int
    b error 
}
x := foo{ 1, nil}
x[0] == 1
x[1] == nil

or

x.0 == 1
x.1 == nil 

Добавить сопоставление с образцом

a, b := x 

Затем создание () создания анонимной структуры из типов

x := (int,error){ 1, nil } 

Это тот же синтаксис, который в настоящее время используется сигнатурами функций!

func() (int, error) { … }

return — это особый случай, когда {} не требуется. Немного углубившись в сигнатуры функций, мы назвали возвраты,

( x int, err error ) 

Это очень похоже на анонимную структуру! Так что сделай

struct { x int, err error } == ( x int, err error ) 

интересно,

func( x int, y int ) error 

можно рассматривать как определение сопоставления анонимной структуры с анонимной структурой. С неявной деструктуризацией

func( x int, y int ) (z int, err error ) {
    return x + y, nil 
}

семантически совпадает с

func( __internal__ struct {x int, y int }( z int, err error ) {
    x, y := __internal__.x, __internal__.y
    var __return__ struct{x int, err error}
    __return__.z = x + y 
    __return__.err = nil 
    return __return__
}

Но почему? Ну, во-первых, это обращается к моему чувству последовательности, но также начинает открывать альтернативы обработке ошибок и цепочке функций, как указано выше.

Я также хотел бы отметить, что другие языки обрабатывают кортежи таким образом, на самом деле я был создателем этого стиля кортежа для Джулии.

NamedTuples · Пакеты Julia

Так иди, а ты? Подробнее в части 2