#prog #go #article
Golang is not a good language
And its creators don't think you're a good developer.
(17.10.2021)
A month or two ago, I put an image of a tierlist of languages that I like using in my Github readme, ranked from F to S tier. F being my least favorite, and S being my favorite.
<...>
But gophers were FURIOUS that their favorite language was the only one at F tier and demanded an explanation from me, pressing a metaphorical knife to my throat.
So let me explain what I have against Go. Also, just as a disclaimer, I don’t like hating on languages too much. Most of them just want to be tools and have their own shortcomings. But a lot of problems Go experiences seem to be self-imposed restrictions through an ideology that wilfully ignores decades of important language research, which just doesn’t make sense to me.
Golang is not a good language
And its creators don't think you're a good developer.
(17.10.2021)
A month or two ago, I put an image of a tierlist of languages that I like using in my Github readme, ranked from F to S tier. F being my least favorite, and S being my favorite.
<...>
But gophers were FURIOUS that their favorite language was the only one at F tier and demanded an explanation from me, pressing a metaphorical knife to my throat.
So let me explain what I have against Go. Also, just as a disclaimer, I don’t like hating on languages too much. Most of them just want to be tools and have their own shortcomings. But a lot of problems Go experiences seem to be self-imposed restrictions through an ideology that wilfully ignores decades of important language research, which just doesn’t make sense to me.
xetera.dev
Golang is not a good language
Xetera's Blog
#prog #go #java #article
NilAway: Practical Nil Panic Detection for Go
Инструмент для статического анализа кода на Go для обнаружения потенциальных разыменований nil-указателей. В отличие от прочих решений, решающих эту проблему, NilAway быстр, анализирует код между функциями (и даже между пакетами) и поддерживает инкрементальный анализ. При всём этом он не требует никаких аннотаций в коде.
А ранее Uber сделали аналогичный инструмент для Java, NullAway.
NilAway: Practical Nil Panic Detection for Go
Инструмент для статического анализа кода на Go для обнаружения потенциальных разыменований nil-указателей. В отличие от прочих решений, решающих эту проблему, NilAway быстр, анализирует код между функциями (и даже между пакетами) и поддерживает инкрементальный анализ. При всём этом он не требует никаких аннотаций в коде.
А ранее Uber сделали аналогичный инструмент для Java, NullAway.
#prog #go #suckassstory
Пусть есть вот такая простая программа на Go:
Если запустить эту программу при отсутствии сетевого подключения (например, на Go playground), то программа печатает ошибку и... Валится с nil pointer dereference:
Почему так — в Go же в целом методы обычно не паникуют с nil-ресивером? Функция net.Dial из стандартной библиотеки возвращает
Так вот, как пояснено в 50 shades of Go, у присваивания интерфейсам
Да, это значит, что поведение может поменяться, если
(thanks @HowToGoWrong)
Пусть есть вот такая простая программа на Go:
package main
import (
"fmt"
"net"
)
func main() {
func() {
f, err := net.Dial("tcp", "1.1.1.1:443")
defer f.Close()
fmt.Println(err)
}()
}
Если запустить эту программу при отсутствии сетевого подключения (например, на Go playground), то программа печатает ошибку и... Валится с nil pointer dereference:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4d0adb]
goroutine 1 [running]:
main.main.func1()
/tmp/sandbox1770654708/prog.go:11 +0x3b
main.main()
/tmp/sandbox1770654708/prog.go:14 +0xf
Почему так — в Go же в целом методы обычно не паникуют с nil-ресивером? Функция net.Dial из стандартной библиотеки возвращает
(Conn, error)
, где Conn
— не конкретный тип, а интерфейс (почему он включает в себя методы Read
и Write
вместо включения интерфейсов io.Reader и io.Writer — отдельный вопрос).Так вот, как пояснено в 50 shades of Go, у присваивания интерфейсам
nil
есть два значения. Если интерфейсу присваивается nil
-значение некоего не-интерфейсного типа, который может быть nil
(скажем, некий указатель), то значимая часть интерфейса также будет nil
, но указатель на таблицу методов будет заполнен от типа присваиваемого значения. Такая переменная будет давать false
при тестирование на равенство с nil
. Если же значению интерфейсного типа присвоить литерал nil
напрямую (или просто не инициализировать явно), то тип нижележащего значения вывести неоткуда, а потому и значимая часть интерфейса, и указатель на таблицу методов будут nil
. Такое значение будет давать true
при тестировании на равенство с nil
.net.Dial
, как и большинство функций в Go, возвращают первым значением nil
в случае ошибки. В коде выше в конце main
после Println
срабатывает код в defer
, который пытается вызывать метод Close
, и так как у nil
-интерфейса указатель на таблицу методов является nil
, рантайм паникует, так как вытащить метод из ниоткуда, очевидно, нельзя.Да, это значит, что поведение может поменяться, если
net.Dial
начнёт возвращать первое значение при ошибке иначе.(thanks @HowToGoWrong)
go.dev
Go Playground - The Go Programming Language
#prog #go #article
Understanding Real-World Concurrency Bugs in Go (PDF)
In this paper, we perform the first systematic study on concurrency bugs in real Go programs. We studied six popular Go software including Docker, Kubernetes, and gRPC. We analyzed 171 concurrency bugs in total, with more than half of them caused by non-traditional, Go-specific problems. Apart from root causes of these bugs, we also studied their fixes, performed experiments to reproduce them, and evaluated them with two publicly-available Go bug detectors.
<...>
Our study found that message passing does not necessarily make multithreaded programs less error-prone than shared memory. In fact, message passing is the main cause of blocking bugs.
<...>
We believe that message passing offers a clean form of inter-thread communication and can be useful in passing data and signals. But they are only useful if used correctly, which requires programmers to not only understand message passing mechanisms well but also other synchronization mechanisms of Go.
Надо отметить, что результаты могут быть искажены тем, что:
а) выборка только из шести проектов (Docker, Kubernetes, etcd, CockroachDB, BoltDB, gRPC-go);
б) рассматриваются только баги, которые были исправлены.
Understanding Real-World Concurrency Bugs in Go (PDF)
In this paper, we perform the first systematic study on concurrency bugs in real Go programs. We studied six popular Go software including Docker, Kubernetes, and gRPC. We analyzed 171 concurrency bugs in total, with more than half of them caused by non-traditional, Go-specific problems. Apart from root causes of these bugs, we also studied their fixes, performed experiments to reproduce them, and evaluated them with two publicly-available Go bug detectors.
<...>
Our study found that message passing does not necessarily make multithreaded programs less error-prone than shared memory. In fact, message passing is the main cause of blocking bugs.
<...>
We believe that message passing offers a clean form of inter-thread communication and can be useful in passing data and signals. But they are only useful if used correctly, which requires programmers to not only understand message passing mechanisms well but also other synchronization mechanisms of Go.
Надо отметить, что результаты могут быть искажены тем, что:
а) выборка только из шести проектов (Docker, Kubernetes, etcd, CockroachDB, BoltDB, gRPC-go);
б) рассматриваются только баги, которые были исправлены.
ACM Conferences
Understanding Real-World Concurrency Bugs in Go | Proceedings of the Twenty-Fourth International Conference on Architectural Support…
Forwarded from Находки в опенсорсе
Статический анализ GitHub Actions
Сразу после релиза новой версии линтера, я задался вопросом обновления своего шаблона для создания новых питоновских библиотек: https://github.com/wemake-services/wemake-python-package
И я понял, что я несколько отстал в вопросе стат анализа GitHub Actions и прочей инфраструктуры.
Расскажу о своих находках.
pre-commit ci
Все знают про пакет pre-commit? Несколько лет назад он получил еще и свой собственный CI, который умеет запускаться без дополнительного конфига. И автоматически пушить вам в ветку любые изменения. Что супер удобно для всяких
Строить CI на базе
- Автоматически исправляются многие проблемы
- Автоматически запускается CI, 0 настроек
- Локально все тоже работает одной командой:
actionlint
Первый раз я увидел
Даже умеет автоматом shellcheck запускать на ваши
zizmor
Исходники. Уже на #rust, он более злой. Делает похожие вещи: находит проблемы безопасности. Находит много проблем.
Вот пример, сколько всего он нашел в mypy.
check-jsonschema
Еще есть вот такой проект, он в основном полезен за счет доп интеграций: можно проверять
Ставится просто как:
Выводы
Как всегда – статический анализ многому меня научил. Я узнал много нового про безопасность GitHub Actions, про вектора атаки, про лучшие практики. А сколько проблем в ваших actions?
Скоро ждите весь новый тулинг в python шаблоне
Сразу после релиза новой версии линтера, я задался вопросом обновления своего шаблона для создания новых питоновских библиотек: https://github.com/wemake-services/wemake-python-package
И я понял, что я несколько отстал в вопросе стат анализа GitHub Actions и прочей инфраструктуры.
Расскажу о своих находках.
pre-commit ci
Все знают про пакет pre-commit? Несколько лет назад он получил еще и свой собственный CI, который умеет запускаться без дополнительного конфига. И автоматически пушить вам в ветку любые изменения. Что супер удобно для всяких
ruff
/ black
/ isort
и прочего. У нас такое стоит в большом количестве проектов. Вот пример из typeshed. Вот что поменялось автоматически. Строить CI на базе
pre-commit
очень удобно, потому что тебе просто нужно скопировать пару строк в конфиг. А плюсов много:- Автоматически исправляются многие проблемы
- Автоматически запускается CI, 0 настроек
- Локально все тоже работает одной командой:
pre-commit run TASK_ID -a
actionlint
Первый раз я увидел
actionlint
внутри CPython и затащил его в mypy. Actionlint на #go, он предлагает набор проверок для ваших GitHub Actions от безопасности до валидации спеки вашего yml. Довольно полезно, позволяет найти много мест для улучшений.
test.yaml:3:5: unexpected key "branch" for "push" section. expected one of "branches", ..., "workflows" [syntax-check]
|
3 | branch: main
| ^~~~~~~
test.yaml:10:28: label "linux-latest" is unknown. available labels are "macos-latest", ..., "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file [runner-label]
|
10 | os: [macos-latest, linux-latest]
| ^~~~~~~~~~~~~
test.yaml:13:41: "github.event.head_commit.message" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions for more details [expression]
|
13 | - run: echo "Checking commit '${{ github.event.head_commit.message }}'"
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Даже умеет автоматом shellcheck запускать на ваши
run:
скрипты!zizmor
Исходники. Уже на #rust, он более злой. Делает похожие вещи: находит проблемы безопасности. Находит много проблем.
Вот пример, сколько всего он нашел в mypy.
warning[artipacked]: credential persistence through GitHub Actions artifacts
--> mypy/.github/workflows/mypy_primer.yml:37:9
|
37 | - uses: actions/checkout@v4
| _________-
38 | | with:
39 | | path: mypy_to_test
40 | | fetch-depth: 0
| |________________________- does not set persist-credentials: false
|
= note: audit confidence → Low
error[dangerous-triggers]: use of fundamentally insecure workflow trigger
--> mypy/.github/workflows/mypy_primer_comment.yml:3:1
|
3 | / on:
4 | | workflow_run:
... |
7 | | types:
8 | | - completed
| |_________________^ workflow_run is almost always used insecurely
|
= note: audit confidence → Medium
check-jsonschema
Еще есть вот такой проект, он в основном полезен за счет доп интеграций: можно проверять
dependabot.yml
, renovate.yml
, readthedocs.yml
и многое другое.Ставится просто как:
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.30.0
hooks:
- id: check-dependabot
- id: check-github-workflows
Выводы
Как всегда – статический анализ многому меня научил. Я узнал много нового про безопасность GitHub Actions, про вектора атаки, про лучшие практики. А сколько проблем в ваших actions?
Скоро ждите весь новый тулинг в python шаблоне
v2025
😎GitHub
GitHub - wemake-services/wemake-python-package: Bleeding edge cookiecutter template to create new python packages
Bleeding edge cookiecutter template to create new python packages - wemake-services/wemake-python-package
#prog #typescript
В Microsoft решили из-за проблем с производительностью переписать компилятор Typescript с Typescript на... #Go. Выбор языка аргументируют сочетанием контроля над раскладкой структур в памяти вкупе со сборщиком мусора и лёгкостью портирования уже имеющегося кода. На мой взгляд, очень странный выбор.
Производительность, впрочем, действительно улучшилась — прототип уже в состоянии компилировать реальные проекты на порядок быстрее.
В Microsoft решили из-за проблем с производительностью переписать компилятор Typescript с Typescript на... #Go. Выбор языка аргументируют сочетанием контроля над раскладкой структур в памяти вкупе со сборщиком мусора и лёгкостью портирования уже имеющегося кода. На мой взгляд, очень странный выбор.
Производительность, впрочем, действительно улучшилась — прототип уже в состоянии компилировать реальные проекты на порядок быстрее.
Microsoft News
A 10x Faster TypeScript
Embarking on a native port of the existing TypeScript compiler and toolset to achieve a 10x performance speed-up.