LINUX.ORG.RU

Выпуск Go 1.22

 ,


1

3

Представлен релиз языка программирования Go 1.22, который развивается компанией Google при участии сообщества как гибридное решение, сочетающее высокую производительность компилируемых языков с такими достоинствами скриптовых языков, как лёгкость написания кода, быстрота разработки и защищённость от ошибок. Код проекта распространяется под лицензией BSD.

Синтаксис Go основан на привычных элементах языка Си с отдельными заимствованиями из языка Оберон. Язык достаточно лаконичен, но при этом код легко читается и воспринимается. Код на языке Go компилируется в обособленные бинарные исполняемые файлы, выполняемые нативно, без использования виртуальной машины (модули профилирования, отладки и другие подсистемы выявления проблем на этапе выполнения интегрируются в виде runtime-компонентов), что позволяет добиться производительности, сопоставимой с программами на языке Си.

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

Среди изменений в новом выпуске:

  • В циклы «for» добавлена поддержка определения диапазонов из целых чисел, например, для перебора значений с 0 до 9 теперь можно использовать цикл «for i := range 10 {...}».
  • В циклы «for» добавлена экспериментальная (GOEXPERIMENT=rangefunc) поддержка функций определения диапазона, позволяющая указывать функцию в качестве итератора. Например, «for i, x := range slices.Backward(s) {...}»
  • Решена давняя проблема с циклами «for», приводившая при вызове сопрограмм (goroutine) к совместному использованию переменных цикла в разных итерациях. Например, код
          values := []string{"a", "b", "c"}
          for _, v := range values {
               go func() {
                   fmt.Println(v)
                  done <- true
               }()
          }
    теперь будет выводить «a»,«b» и «c», а не только «c», как было раньше.
  • Проведена оптимизация работы с памятью в runtime, которая привела к повышению производительности на 1-3% и снижению потребления памяти в большинстве приложений на 1%.
  • Продолжена работа по задействованию в компиляторе оптимизаций на основе результатов профилирования кода (PGO - Profile-guided optimization), позволяющих учитывать особенности, определяемые во время выполнения программы. В новой версии в компиляторе задействованы средства девиртуализации для замены непрямых вызовов различных методов на выполнение развёрнутых inline-блоков.
  • При включении PGO добавленное изменение позволило повысить производительность большинства программ на 2-14%.
  • В компилятор добавлена экспериментальная (GOEXPERIMENT=newinliner) улучшенная реализация механизма развёртывания (inlining) вызовов, использующая эвристику для разделения важных и второстепенных операций.
  • В стандартную библиотеку добавлен пакет «math/rand/v2», в котором предложен более целостный API и задействованы более быстрые алгоритмы генерации псевдо-случайных чисел.
  • В пакет net/http.ServeMux добавлена возможность указания методов и масок в шаблонах, например, шаблон «GET /static/{id}/» будет применён к запросам с HTTP-методом «GET» и сохранит значение второго сегмента запрошенного пути в идентификаторе «id».
  • В пакет database/sql добавлена поддержка типа Null[T], позволяющего сканировать столбцы, которые могут принимать значение NULL. В пакет slices добавлена функция Concat для слияния нескольких слайсов любого типа.
  • В командах для работы с рабочими пространствами (коллекциями модулей) предоставлена возможность использования каталога «vendor», содержащего зависимости к содержимому рабочего пространства. Каталог создаётся при выполнении команды «go work vendor» и используется в сборочных командах при выставлении опции "-mod=vendor" (включает по умолчанию при наличии каталога vendor).

Изменения в поведении утилит.

  • go get больше не поддерживается за пределами модуля в устаревшем GOPATH режиме (то есть с GO111MODULE=off). Другие команды сборки, такие как go build и go test, будут продолжать работать для устаревших GOPATH программ в течение неопределенного времени.
  • go mod init больше не пытается импортировать требования к модулям из файлов конфигурации для других инструментов поставщиков (таких как Gopkg.lock).
  • go test -cover теперь печатает сводные данные о покрытии для покрываемых пакетов, у которых нет собственных тестовых файлов. До Go 1.22 go test -cover для такого пакета сообщал бы
    ? mymod/mypack [no test files]

    и теперь с Go 1.22 функции в пакете считаются непокрытыми:

    mymod/mypack coverage: 0.0% of statements
    
    Обратите внимание: если пакет вообще не содержит исполняемого кода, мы не можем сообщить о значимом проценте покрытия; для таких пакетов go test будет продолжать сообщать об отсутствии тестовых файлов.

  • Веб-интерфейс инструмента trace был слегка обновлен в рамках работы по поддержке нового трассировщика, решены некоторые проблемы и улучшена читабельность различных страниц. Веб-интерфейс теперь поддерживает изучение трассировок в поточно-ориентированном представлении. Средство просмотра трассировки теперь также отображает полную продолжительность всех системных вызовов. Эти улучшения применимы только для просмотра трассировок, созданных программами, созданными на Go 1.22 или новее. В будущем выпуске некоторые из этих улучшений будут внесены в трассировки, создаваемые старой версией Go.
  • Среда выполнения теперь хранит метаданные сборки мусора на основе типов ближе к каждому объекту кучи. Это изменение также снижает затраты памяти большинства программ Go примерно на 1% за счет дедупликации избыточных метаданных. В некоторых программах улучшение может быть меньшим, поскольку это изменение корректирует границы класса размера распределителя памяти, поэтому некоторые объекты могут быть перемещены на класс размера выше. Следствием этого изменения является то, что адреса некоторых объектов, которые раньше всегда были выровнены по границе 16 байт (или выше), теперь будут выровнены только по границе 8 байт. Некоторые программы, использующие инструкции ассемблера, требующие, чтобы адреса памяти были выровнены по размеру более 8 байт и полагаются на предыдущее поведение выравнивания распределителя памяти, могут выйти из строя, но мы ожидаем, что такие программы будут редки. Такие программы могут быть созданы с GOEXPERIMENT=noallocheaders с возможностью возврата к старой модели метаданных и восстановления предыдущего поведения выравнивания, но владельцам пакетов следует обновить свой ассемблерный код, чтобы избежать предположения о выравнивании, поскольку этот обходной путь будет удален в будущем выпуске.
  • Как упоминалось в примечаниях к выпуску Go 1.20, Go 1.22 теперь требует финальной версии Go 1.20 или новее для начальной сборки. Мы ожидаем, что Go 1.24 потребует финальной версии Go 1.22 или более поздней версии для начальной сборки.
    Оригинал (go.dev)

>>> Подробности (OpenNet)

★★★★★

Проверено: hobbit ()

да нормальный язык, че вы пердите. строго типизированный, библиотек много, производительный. демона запилить или микросервис сделать ваще огонь. путь будет. под пивас пойдет

Unixson
()
Последнее исправление: Unixson (всего исправлений: 1)
Ответ на: комментарий от Ghostwolf

Всратость того, что обращение к полям структуры, переданной по указателю и по значению в метод, одно и тоже - остаётся.

fluorite ★★★★★
()
Ответ на: комментарий от apt_install_lrzsz

Ужо давно добавили.

func MapKeys[K comparable, V any](m map[K]V) []K {
    r := make([]K, 0, len(m))
    for k := range m {
        r = append(r, k)
    }
    return r
}

urxvt ★★★★★
()

Шикарный релиз. Го с каждым днём всё лучше. И даже генерики его не так уж сильно испортили!

vbr ★★★
()

Синтаксис Go основан на привычных элементах языка Си

???

Да ладно, от Си там может быть только фигурные скобки есть. Так они в куче других языков используются. Разработчикам Go хватило ума не пихать тип в начало объявления переменной, и уже только это дает возможность по-человечески читать декларации, а не как в сишечке по спирали.

Xintrea ★★★★★
()
Ответ на: комментарий от thegoldone

Я про человеческий фактор. Ловил баги и использованием неявного типа когда присваивалось значение переменной типа any (точнее там была map[any]) , а в другом месте использовался явный тип инта с размерностью. Даже при дебаге (принтом) было неочевидно - записали 123 в мапу, ищем в ней 123, но не находило ибо типы разные а при печати значения обы выводили 123.

Проще говоря, лучше использовать явные типы. Меньше подобных багов. В том числе меньше сюрпризов на разных архитектурах (32, 64). Тот же инт - он разный, зависит от архитектуры.

ergo ★★★
()
Последнее исправление: ergo (всего исправлений: 1)
Ответ на: комментарий от Unixson

Собственно, это тот самый Паскаль, которого я и хотел.

LongLiveUbuntu ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

А в новых языках уходят от схемы type var к схеме var type, ибо и правда удобнее. Как можно тридцать лет себя насиловать - ума не приложу.

LongLiveUbuntu ★★★★★
() автор топика

И как обычно в ЛОРовских традициях, в новости о новой версии ЯП, целую страницу обсуждают какую-то минорную синтаксическую мелочь. Мда…

seiken ★★★★★
()
Ответ на: комментарий от Ghostwolf

Я это про то что кто тут написал что его прога получилась по скорости как на си.

mx__ ★★★★★
()
Ответ на: комментарий от liksys

В прочтении более-менее сложных конструкций. Да даже банальное int *a, b может ввести в заблуждение.

LongLiveUbuntu ★★★★★
() автор топика

Здорово, обновлю на Plan 9

buddhist ★★★★★
()
Ответ на: комментарий от ergo

Писать явно тип, когда он очевиден, а в выражении

var i = 10

это очевидный int, не нужно.

Если кто-то использует interface{} вместо целого, то его нужно на скриптфак отправить, а не дебажить его говнокод.

Если кто-то не в курсе, что такое interface{}, то ему нужно это изучить.

Тип и так и так явный. Он не может быть неявным. Явный int. При преобразовании в interface{} – это явный interface{}.

Такое ощущение, что овладеть языком как инструментом не получилось. И началось костылевание собственного этого упущения методом написания int. Да ещё с каким-то суеверным подходом.

Тогда скорее нужно 10 раз отжаться и 10 раз присесть. Оно точно работает. Нужно только чаще повторять. 100%.

thegoldone
()
Ответ на: комментарий от LongLiveUbuntu

Испытал влияние: Си, Оберон-2, Limbo, Active Oberon, BCP, Паскаль, Оберон, Smalltalk, Newsqueak, Модула-2, Alef, APL, BCPL, Модула и Оккам

Ты забыл добавить в список BDSM и LGBTQ!!!

no-dashi-v2 ★★
()
Ответ на: комментарий от seiken

Ну в 2020-х форсить стиль K&R, объясняя это при помощи usual noreason «у нас зато более быстрый транслятор и авторасстановка точек с запятой, чо пристали», чтоб тут же их потроллили упоминанием молниеносных трансляторов паскале-оберонов, которым с 70х пофиг в строчку BEGIN или с новой строки и тут же появился форк go, который разрешает любое расположение скобок — ну такое :)

slackwarrior ★★★★★
()

Тот случай, когда столь подробное описание, что такое Go в начале новости не требуется. Аудитория более-менее знает, что такое Go (а кто не знает, всё равно ничего не поймёт, достаточно сказать, что ЯП). Когда очередной редактор Васи Пупкина для конфигов программы от Пети Петушкова обновляется — вечно не пишут, что это. А как что-то крупное — так на тебе. Хех…

CrX ★★★
()
Ответ на: комментарий от AlexLorovitch

Видите у вас слишком хороший комп для этого, но все равно видно разницу. Вот я взял старый ноут …

time ./a.out 
Number 0
real	0m23,131s
user	0m23,052s
sys	0m0,012s

time ./main 
Number 0

real	0m30,820s
user	0m30,692s
sys	0m0,035s

И если увеличить и число во много раз и разница будет нарастать.

mx__ ★★★★★
()
Ответ на: комментарий от LongLiveUbuntu

Я себя программистом по go не считаю …

package main

import "fmt"

func slow_sqrt(nbr int) (i int) {
    i = 1
    for i < nbr {
        if nbr/i == i {
            return i
        }
    i++
    }
    return 0
}

func main() {
    fmt.Println("Number", slow_sqrt(2147483646))
}
mx__ ★★★★★
()
Ответ на: комментарий от thegoldone

Если кто-то не в курсе, что такое interface{}, то ему нужно это изучить.

ох, сколько самомнения :)

ergo ★★★
()
Ответ на: комментарий от Syncro

стало максимально быстро?

Это будет быстрее, чем в Go

X-Pilot ★★★★★
()
Ответ на: комментарий от mx__

Я себя программистом по go не считаю …

Аналогично :) Пишу в основном на С++, но к go присматривался …
По тесту - опции для С - O3 -s
для go - build -ldflags=-w

gcc9.4 и go1.22 соответственно.

Если взять старенький go ( до 1.14) наверное будет хуже …

AlexLorovitch
()
Ответ на: комментарий от AlexLorovitch

gcc 8.5 и go 1.20

опции никакие на ставил ни там ни там.

Еще раз повторяю, у меня дохлый ноут, и если вы хотите увидеть большую разницу тупо увеличите в несколько раз число.

не понятно в чем спор, не может язык с сборщиком быть сопоставим по скорости ни как.

P.S. И кстати в свое время я как не бился не осилил в GO динамическую линковку, это что не возможно ?

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Хм если увеличить до 9147483646, то тестик стремительно завершается с идентичным результатом
Number 95642

Кстати в С пришлось внедрять long int, а в go оно по дефолту.

Я гонял тоже незатейливый тест, но с double с разными ЯП и получалось, что с подобными простыми операциями все компилируемые языки сопоставимы с С.

GC здесь ведь не используется, как и прочие хитрости типа проверок на выход за границы массивов.

С shared вроде есть флаги, но я не использовал.

AlexLorovitch
()
Ответ на: комментарий от her_s_gory

Да я понимаю. Так, крышечкой похлопал. 🤪

beck ★★★★
()
Ответ на: комментарий от mx__

Го, магический комментарий имеет значение

package main

import "C"

//export SlowSqrt
func SlowSqrt(nbr C.int) (i C.int) {
	i = 1
	for i < nbr {
		if nbr/i == i {
			return i
		}
		i++
	}
	return 0
}

func main() {}

go build -buildmode=c-shared
mv -v slowsqrt libslowsqrt.so

Си

#include "slowsqrt.h"
#include <stdio.h>

int main(void) {
  printf("Number %d", SlowSqrt(2147483646));
  return 0;
}
gcc -L. -I. main.c -l slowsqrt

Запуск

LD_LIBRARY_PATH=. ./a.out

Примеры – https://github.com/vladimirvivien/go-cshared-examples
Удаление -buildmode=sharedhttps://github.com/golang/go/issues/47788 (Go 1.18+)

thegoldone
()
Последнее исправление: thegoldone (всего исправлений: 1)

Отличный релиз отличного ЯП

umren ★★★★★
()

да кому нужен этот ваш Go?) есть средства контейнеризации без подвязки к Golang, его продвигают только поборники проприетарщины) что все продукты от Google имеют только одну цель - это слежка за людьми, думаю не для кого не станет секретом, вот выбор Perl я считиаю мужским

maerLLM
()
Ответ на: комментарий от LongLiveUbuntu

странно же python например не собирается pythonом, а C ?

Т е чтобы собрать Go 1.0 нужно искать древний Go, а не православный С?

ivanich10
()
Ответ на: комментарий от ivanich10

Ты дурачок? Понятие «раскрутка компилятора» тебе знакомо?

LongLiveUbuntu ★★★★★
() автор топика
Ответ на: комментарий от mx__

Если нужен исполняемый файл с динамической библиотекой. И то и другое на Го, то через Си только. Вариант с shared удалён, как сказано выше.

Есть ещё возможность использовать plugin. Но только для Linux, и BSD вроде. Но зато на чистом Го. Проблема. Он тащит зависимости с собой и маленький плагин с большими зависимостями притащит их с собой. По крайней мере на размер файла это повлияет.

thegoldone
()
Последнее исправление: thegoldone (всего исправлений: 1)
Ответ на: комментарий от ivanich10

Го 1.4 собирается Сями. А Го 1.5 уже собирается Гошкой. И все дальнейшие.

thegoldone
()
Ответ на: комментарий от thegoldone

Это все понятно, походу из за сборщика и прочего нет смысла делать shared все равно он притащит весь свой рантайм… Ну им виднее.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Со сборщиком мусора удалось решить все вопросы, когда собственно shared и появился. В основном проблемы связаны с версиями и модулями, сборкой.

Если интересуют детали – https://github.com/golang/go/issues/47788#issuecomment-954890659 (англ.).

Если проэкстраполировать, то им просто никто не занимался толком, и он безнадёжно отстал от прогресса языка в целом. Видимо не очень нужен, раз так.

Если у каждого приложения своя версия зависимости, то каждому нужна своя версия разделяемой библиотеки. Что ставит под сомнение необходимость разделения.

thegoldone
()
Последнее исправление: thegoldone (всего исправлений: 1)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.