1.84K subscribers
3.41K photos
134 videos
15 files
3.66K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
😁16🤡3
#prog #go #article

What’s New in Go 1.22: slices.Concat

<...>

Early versions of the Concat proposal included a destination slice argument, like append. (Concat(dest []T, ss ...[]T) []T.) Why doesn’t the final version of slices.Concat have a destination argument to allow users to reuse an existing slice as backing?

The issue
goes back to what is called the problem of aliasing. <...> But what if you are concatenating the parts of a slice onto itself? Take this example:

s := []int{1, 2, 3, 4}
_ = slices.ConcatWithDestination(s[:0], s[3:4], s[2:3], s[1:2], s[0:1])
// What is s now?


A naïve implementation of slices.ConcatWithDestination would clobber the 1 at the start of the slice with 4 before copying it onto the end of the slice, so that you end up with 4, 3, 3, 4 instead of 4, 3, 2, 1 as intended.

<...>

In the end, it was decided that just always returning a new slice would keep the implementation of slices.Concat simpler and help prevent any issues with accidentally aliasing a slice and getting unexpected results, so the destination slice argument was dropped.

(thanks @golang_for_two)
💩10🤡93😁3
#prog #go

6 февраля вышла версия Go 1.22.

Среди прочего в стандартную библиотеку добавлен пакет math/rand/v2. Примечательно это по двум причинам.

Первая: это первый случай, когда в стандартную библиотеку Go добавляют вторую версию пакета. На мой взгляд, это вполне себе довод в пользу того, чтобы не делать std слишком богатой. (Конечно, тут ещё далеко до безобразия Python с urllib3, но кто знает, может, и до этого дойдёт).

Вторая: в proposal на этот пакет упомянуто следующее:

2. Remove Source.Seed, Rand.Seed, and top-level Seed. Top-level Seed is deprecated as of Go 1.20. Source.Seed and Rand.Seed assume that the underlying source can be seeded by a single int64, which is only true of a limited number of sources. Specific source implementations can provide Seed methods with appropriate signatures, or none at all for generators that cannot be reseeded; the details of seeding do not belong in the general interface. [выделение моё]

В оригинальном дизайне rand получение случайных значений действовало через тип Rand, который оборачивал значение, реализующее интерфейс Source:

type Source interface {
Int63() int64
Seed(seed int64)
}

В v2 метод Seed убрали, а метод Int63 поменяли на Int64 — и совершенно верно, ибо в этом интерфейсе торчали уши конкретной дефолтной реализации Source. Однако заявление "the details of seeding do not belong in the general interface", как мне кажется, вызвано не общими соображениями, а ограничениями Go. Именно, в идеале у каждого источника случайности должен быть свой тип для сида — но в Go нельзя сделать тип, который является частью интерфейса и который может быть определён реализацией.

Для сравнения, в растовом rand инициализация из начального значения вынесена в отдельный трейт SeedableRng, где сид определяется через ассоциированный тип.

===========

Другая вещь, которая куда как более стрёмная — это тот факт, что тип Rand может запрашивать данные из Source только через метод Int64, а потому остальные методы не могут эксплуатировать тот факт, что они работают с конкретным типом источника случайности, и потому не могут использовать специфичные для этих типов оптимизации. В частности, реализация Rand.Int32 попросту зовёт Int64 на внутреннем Source и делает битовый сдвиг, отбрасывая младшие 33 бита. Если Rand.Int32 вызывается в цикле, то выходит, что где-то половина работы источника случайности уходит в никуда.
🤔2
#prog #go #article

Hiring Challenge: Smallest Golang Websocket Client

TL;DR: если опуститься до голых сисколов, выкинуть GC, пошаманить с линкером для выкидывания лишних секций и компилировать под 32 бита, то можно уменьшить размер на четыре порядка по сравнению с бейзлайном.

Занятно, что избавление от std уменьшает размер вдвое по сравнению с предыдущим шагом. gc слаб в LTO?

(thanks @go_perf)
🤣9🤔1
#prog #go #article

Go channels are bad and you should feel bad

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

In all of my Go code I work with, I can count on one hand the number of times channels were really the best choice. Sometimes they are. That’s great! Use them then. But otherwise just stop.
👎4👍2🤔1
#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.
💯19🤡15👍1
#prog #go #java #article

NilAway: Practical Nil Panic Detection for Go

Инструмент для статического анализа кода на Go для обнаружения потенциальных разыменований nil-указателей. В отличие от прочих решений, решающих эту проблему, NilAway быстр, анализирует код между функциями (и даже между пакетами) и поддерживает инкрементальный анализ. При всём этом он не требует никаких аннотаций в коде.

А ранее Uber сделали аналогичный инструмент для Java, NullAway.
👍31
Все: обсуждают итераторы и телеметрию в #go релизе 1.23

Я:
👍2🌚1
#prog #go #suckassstory

Пусть есть вот такая простая программа на 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)
💩11🤮4🥴4🤡1🌚1