Endianness или конечность порядок байт
Компьютеры по-разному хранят данные в оперативной памяти.
Меня всегда смущало, читая что-то, где есть двоичное представление
почему у некоторых старший байт слева, а у некоторых справа.
А все потому что люди до сих пор не договорились как хранить данные.
Есть системы, которые хранят от старшего (MSB most significant byte) к младшему (LSB least significant byte), а есть наоборот от LSB к MSB.
MSB и LSB не стоит путать с MSb (most significant bit) и LSb (least significant bit) одно про биты, другое про байты.
В 1980 году для обозначения порядка байтов было введено два понятия: Little-Endians и Big-Endians, ссылаясь на документ под названием Gulliver's Travel (1726 г.).
Little-Endian — (LE) порядок байт от LSB к MSB (слева направо)
Big-Endians — (BE) порядок байт от MSB к LSB (справа налево)
Как выглядит на практике?
Берем
В Little-Endian единица находится слева.
В Big-Endian единица находится справа.
Важно: сами байты не поменялись, поменялся именно их порядок.
И зачем же знать все это дело?
Чтоб в ногу не стрелялось
— При работе с UTF-16, UTF-32 следует помнить про BOM (byte order mark), константа которая поможет определить порядок байт.
В LE это [254 255] в BE это [255 254].
— При сериализации слайс байтов в конкретный тип.
К примеру нам приходит слайс байтов, мы знаем что этот слайс на самом деле uint64.
И если мы сконвертируем через unsafe, мы можем выстрелить в ногу, из-за разности понимания старшого и младшего бита (пример выше).
— Обратный пример использования unsafe:
Результат может быть разным:
- 1 при Little-Endian
- 256 при Big-Endian
В комментарий скину код, который симулирует поведение при LE и при BE.
— В других случаях, которые я еще не придумал.
P.S.
PostgreSQL хранит файлы страниц как представление оперативной памяти, поэтому копирование файлов на другую машину с целью скопировать базу данных может быть ошибкой, из-за порядка байт.
Компьютеры по-разному хранят данные в оперативной памяти.
Меня всегда смущало, читая что-то, где есть двоичное представление
почему у некоторых старший байт слева, а у некоторых справа.
А все потому что люди до сих пор не договорились как хранить данные.
Есть системы, которые хранят от старшего (MSB most significant byte) к младшему (LSB least significant byte), а есть наоборот от LSB к MSB.
В 1980 году для обозначения порядка байтов было введено два понятия: Little-Endians и Big-Endians, ссылаясь на документ под названием Gulliver's Travel (1726 г.).
Little-Endian — (LE) порядок байт от LSB к MSB (слева направо)
Big-Endians — (BE) порядок байт от MSB к LSB (справа налево)
Как выглядит на практике?
const u uint32 = 1
le := make([]byte, 4)
binary.LittleEndian.PutUint32(le, u)
be := make([]byte, 4)
binary.BigEndian.PutUint32(be, u)
fmt.Printf("%b\n", le) // output: [1 0 0 0]
fmt.Printf("%b\n", be) // output: [0 0 0 1]
Берем
1 в uint16, в байтовом представлении у нас должна быть только одна единица в позиции LSB.В Little-Endian единица находится слева.
В Big-Endian единица находится справа.
Важно: сами байты не поменялись, поменялся именно их порядок.
И зачем же знать все это дело?
— При работе с UTF-16, UTF-32 следует помнить про BOM (byte order mark), константа которая поможет определить порядок байт.
В LE это [254 255] в BE это [255 254].
— При сериализации слайс байтов в конкретный тип.
К примеру нам приходит слайс байтов, мы знаем что этот слайс на самом деле uint64.
И если мы сконвертируем через unsafe, мы можем выстрелить в ногу, из-за разности понимания старшого и младшего бита (пример выше).
— Обратный пример использования unsafe:
t := &struct {
first, second uint16
}{
first: 1,
second: 0,
}
v := *(*uint32)(unsafe.Pointer(t))
fmt.Println(v) // output: 256 or 1Результат может быть разным:
- 1 при Little-Endian
- 256 при Big-Endian
В комментарий скину код, который симулирует поведение при LE и при BE.
— В других случаях, которые я еще не придумал.
P.S.
PostgreSQL хранит файлы страниц как представление оперативной памяти, поэтому копирование файлов на другую машину с целью скопировать базу данных может быть ошибкой, из-за порядка байт.
✍4💅3❤2
Небольшой факт:
Название операционной системы Plan 9, а если быть точнее Plan 9 from Bell Labs было вдохновлено очень спорным фильмом Plan 9 from Outer Space.
Как связана эта ОСь с тематикой канала?
Команду Plan 9 возглавляли: Rob Pike, Ken Thompson, они же в дальнейшем работали над Golang и многое привнесли из Plan 9 в сам язык.
На эту тему могу посоветовать доклад: Почему Golang такой странный.
Достойно упоминания:
Plan 9 строился на идее Name Space, спустя 10 лет подобный функционал появился в Linux под названием: namespaces это одна из основ контейнеризации.
Название операционной системы Plan 9, а если быть точнее Plan 9 from Bell Labs было вдохновлено очень спорным фильмом Plan 9 from Outer Space.
Как связана эта ОСь с тематикой канала?
Команду Plan 9 возглавляли: Rob Pike, Ken Thompson, они же в дальнейшем работали над Golang и многое привнесли из Plan 9 в сам язык.
На эту тему могу посоветовать доклад: Почему Golang такой странный.
Достойно упоминания:
Plan 9 строился на идее Name Space, спустя 10 лет подобный функционал появился в Linux под названием: namespaces это одна из основ контейнеризации.
✍2💅2👾1
Как же я люблю находить хитрые оптимизации внутри Go.
src/strconv/itoa.go
И функции, которые возвращают строковое представление по целочисленному типу используют эту микро оптимизацию.
Не могу описать свой восторг, когда натыкаюсь на подобное.
src/strconv/itoa.go
// small returns the string for an i with 0 <= i < nSmalls.
func small(i int) string {
if i < 10 {
return digits[i : i+1]
}
return smallsString[i*2 : i*2+2]
}
const nSmalls = 100
const smallsString = "00010203040506070809" +
"10111213141516171819" +
"20212223242526272829" +
"30313233343536373839" +
"40414243444546474849" +
"50515253545556575859" +
"60616263646566676869" +
"70717273747576777879" +
"80818283848586878889" +
"90919293949596979899"
И функции, которые возвращают строковое представление по целочисленному типу используют эту микро оптимизацию.
Не могу описать свой восторг, когда натыкаюсь на подобное.
GitHub
go/src/strconv/itoa.go at 70f4717e96cf9d8ca8a5f439d7d6487ec822ce49 · golang/go
The Go programming language. Contribute to golang/go development by creating an account on GitHub.
🔥3✍2💅2
Forwarded from Lasiar работает 💡
Еще нечто подобное есть в пакете
src/net/textproto/reader.go
Для того чтоб избежать копирования слайса байт при
src/net/textproto/reader.go:782
net/textproto, функционал которого использует net/http.Header{} для канонизации.src/net/textproto/reader.go
func initCommonHeader() {
commonHeader = make(map[string]string)
for _, v := range []string{
"Accept",
"Accept-Charset",
"Accept-Encoding",
...
"X-Powered-By",
} {
commonHeader[v] = v
}
}Для того чтоб избежать копирования слайса байт при
string(a):src/net/textproto/reader.go:782
// The compiler recognizes m[string(byteSlice)] as a special
// case, so a copy of a's bytes into a new string does not
// happen in this map lookup:
if v := commonHeader[string(a)]; v != "" {
return v, true
}
return string(a), true
🔥2💅2✍1👾1
Давно не следил за SwissMap в Golang.
И кажется, есть вероятность, что в Go 1.24 поменяется алгоритм мап на Swiss Tables.
Три недели назад в master ветке появился коммит:
Почитать про SwissMap можно тут:
Оригинальный issue: тык
Описание Swiss Tables: тык
Success story команды DoltDB: тык
И кажется, есть вероятность, что в Go 1.24 поменяется алгоритм мап на Swiss Tables.
Три недели назад в master ветке появился коммит:
internal/runtime/maps: initial swiss table map implementation
Почитать про SwissMap можно тут:
Оригинальный issue: тык
Описание Swiss Tables: тык
Success story команды DoltDB: тык
🔥6💅4👍1🥰1
Небольшое напоминание о том, что каналы необязательно закрывать.
Об этом еще писал Rob Pike в 2011 году.
https://groups.google.com/g/golang-nuts/c/pZwdYRGxCIk/m/rGr1D-uTQMEJ
Об этом еще писал Rob Pike в 2011 году.
https://groups.google.com/g/golang-nuts/c/pZwdYRGxCIk/m/rGr1D-uTQMEJ
✍9👍3💅3🥰1🤝1
TL;DR: Для масштабирования gRPC в K8s, следует взять linkerd или нечто подобное.
Есть некий клиент (
Используя K8s можно достаточно легко горизонтально масштабировать приложение:
- Руками изменить scale.
- Настроить HPA (Horizontal Pod Autoscaling)
И вроде все хорошо — у нас n-ое количество подов, и нагрузка должна автоматом распределятся по round-robin, ведь так?
Тут уже начинаются детали.
Распределение нагрузки будет работать, в зависимости от того, по какому именно транспорту будут общаться сервисы.
K8s использует iptables как балансировщик, а он работает на уровне TCP соединений, то есть может балансировать TCP соединения.
HTTP/1.1: TCP соединения переиспользуются только после завершения HTTP запроса, то есть: в одно и тоже время в одном TCP соединении может обрабатываться только один HTTP запрос.
HTTP/2: Позволяет использовать одно и тоже TCP соединения для нескольких одновременных HTTP запросов (multiplexing).
Следовательно, при HTTP/2 у нас используется одно TCP соединение, внутри которого проходят множество запросов.
Балансировка будет выглядеть так:
Все запросы будут идти на первый сервер.
А gRPC использует HTTP/2 для транспорта.
——
То есть: балансировщик из коробки в K8s для gRPC трафика будет некорректно балансировать нагрузку, иначе говоря: балансировать TCP соединения, а не gRPC запросы.
——
Что делать?
Есть пару вариантов:
1. Взять Linkerd, он умеет балансировать gRPC с коробки.
*ИМХО самый корректный*
2. Так же, можно чуть чаще пересоздавать gRPC соединения, тут про это пишут.
*ИМХО самый простой*
2. Внутри самого сервиса: README.md.
*ИМХО самый странный*
Есть некий клиент (
c) и некий сервер (s) в K8s, линия обозначает TCP соединение.+--+ +--+
|c +---> s|
+--+ +--+
Используя K8s можно достаточно легко горизонтально масштабировать приложение:
- Руками изменить scale.
- Настроить HPA (Horizontal Pod Autoscaling)
И вроде все хорошо — у нас n-ое количество подов, и нагрузка должна автоматом распределятся по round-robin, ведь так?
+--+ +--+
|c +---> s|
+--+ +--+
| +--+
+-----> s|
| +--+
| +--+
+-----> s|
+--+
Тут уже начинаются детали.
Распределение нагрузки будет работать, в зависимости от того, по какому именно транспорту будут общаться сервисы.
K8s использует iptables как балансировщик, а он работает на уровне TCP соединений, то есть может балансировать TCP соединения.
HTTP/1.1: TCP соединения переиспользуются только после завершения HTTP запроса, то есть: в одно и тоже время в одном TCP соединении может обрабатываться только один HTTP запрос.
HTTP/2: Позволяет использовать одно и тоже TCP соединения для нескольких одновременных HTTP запросов (multiplexing).
Следовательно, при HTTP/2 у нас используется одно TCP соединение, внутри которого проходят множество запросов.
Балансировка будет выглядеть так:
+--+ +--+
|c +---> s|
+--+ +--+
+--+
| s|
+--+
+--+
| s|
+--+
Все запросы будут идти на первый сервер.
А gRPC использует HTTP/2 для транспорта.
——
То есть: балансировщик из коробки в K8s для gRPC трафика будет некорректно балансировать нагрузку, иначе говоря: балансировать TCP соединения, а не gRPC запросы.
——
Что делать?
Есть пару вариантов:
1. Взять Linkerd, он умеет балансировать gRPC с коробки.
*ИМХО самый корректный*
2. Так же, можно чуть чаще пересоздавать gRPC соединения, тут про это пишут.
*ИМХО самый простой*
2. Внутри самого сервиса: README.md.
*ИМХО самый странный*
🔥6💅2❤1✍1👍1
Недавно делал пост, в котором предполагал, что алгоритм для map поменяется на Swiss Tables.
А сейчас нахожу, что Swissmaps будут дефолтными, об этом написали в meeting notes.
До этого не было понятно, будут ли они доступны из коробки или через экспериментальный флаг, так как флаг уже реализован в master: flags.go.
Спасибо t.me/crossjoin за наводку)
А сейчас нахожу, что Swissmaps будут дефолтными, об этом написали в meeting notes.
До этого не было понятно, будут ли они доступны из коробки или через экспериментальный флаг, так как флаг уже реализован в master: flags.go.
Спасибо t.me/crossjoin за наводку)
🔥6✍4💅3
Сегодня немного философии.
Откуда мы что-то узнаем?
Думаю многие знают что запуск сервиса на нулевом порту это запуск на случайном открытом порту, но откуда вы это узнали?
В RFC6335 описано как распределяются порты (системные, пользовательские и так далее),
а в IANA описано то, как уже конкретные порты распределяются по сервисам (DNS, HTTP, HTTPS...).
Для TCP и UDP в IANA нулевой порт помечен как зарезервированный, что вообще не описывает реальную ситуацию.
Может сказано в документации Linux?
При открытии сокета, порт впервые появляется в системном вызове bind.
В man упоминается нулевой порт только при ошибке, что опять же не описывает поведение.
Отчаявшись пошел уже читать исходники Linux. И нашел следующую функцию:
Если кратко, то:
Про четный и нечетный порт в следующий раз напишу .
Я ожидал что этот путь будет чуть проще, я его не проходил ранее, но я знал эту информацию.
Откуда мы что-то узнаем?
Думаю многие знают что запуск сервиса на нулевом порту это запуск на случайном открытом порту, но откуда вы это узнали?
В RFC6335 описано как распределяются порты (системные, пользовательские и так далее),
а в IANA описано то, как уже конкретные порты распределяются по сервисам (DNS, HTTP, HTTPS...).
Для TCP и UDP в IANA нулевой порт помечен как зарезервированный, что вообще не описывает реальную ситуацию.
Может сказано в документации Linux?
При открытии сокета, порт впервые появляется в системном вызове bind.
В man упоминается нулевой порт только при ошибке, что опять же не описывает поведение.
Отчаявшись пошел уже читать исходники Linux. И нашел следующую функцию:
/* Obtain a reference to a local port for the given sock,
* if snum is zero it means select any available local port.
* We try to allocate an odd port (and leave even ports for connect())
*/
int inet_csk_get_port(struct sock *sk, unsigned short snum)
Если кратко, то:
Если передается нулевой порт, то аллоцируем нечетный порт
Я ожидал что этот путь будет чуть проще, я его не проходил ранее, но я знал эту информацию.
👍8💅3
В последнее время занимался тем, что немного привел в порядок свой линтер: canonicalheader, который входит в golangci-lint.
Добавил туда возможность конфигурирования, хотя мне эта идея не сильно нравится, но сообщество просило (#39, #12).
Из-за того что упростил еще текст issue, то обновление через dependabot не сработает и нужно будет руками обновить в golangci-lint.
Добавил туда возможность конфигурирования, хотя мне эта идея не сильно нравится, но сообщество просило (#39, #12).
Из-за того что упростил еще текст issue, то обновление через dependabot не сработает и нужно будет руками обновить в golangci-lint.
GitHub
GitHub - lasiar/canonicalheader: Golang linter checking the canonicality of the http header
Golang linter checking the canonicality of the http header - lasiar/canonicalheader
👍4💅4✍2🔥1👾1
В clickhouse есть функция
Учитывая что clickhouse это колоночная база данных, кажется можно оптимизировать чтение строки, особенно если используется кодек без сжатия.
И читая сурсы, кажется, что никаких оптимизаций нет.
Функция left, по сути использует sliceFromLeftDynamicLength, которая принимает IColumn — интерфейс строки в памяти. Соответственно строка уже прочитана из файловой системы.
Несколько грустно, что нет такой оптимизации :(
Дисклеймер:
С++ не мой основной язык, если есть что добавить — добро пожаловать в комментарии.
left(s, offset)Учитывая что clickhouse это колоночная база данных, кажется можно оптимизировать чтение строки, особенно если используется кодек без сжатия.
И читая сурсы, кажется, что никаких оптимизаций нет.
Функция left, по сути использует sliceFromLeftDynamicLength, которая принимает IColumn — интерфейс строки в памяти. Соответственно строка уже прочитана из файловой системы.
Несколько грустно, что нет такой оптимизации :(
Дисклеймер:
С++ не мой основной язык, если есть что добавить — добро пожаловать в комментарии.
🤪3🔥2💅2👾1
Благодаря golangci-lint, я узнал о некой проблеме. В некоторых конфигурациях происходит деградация производительности при работе Go в контейнере с ограничением по CPU.
TLDR:
Просто используй https://github.com/uber-go/automaxprocs.
За что отвечает GOMAXPORCS:
За количество threads процесса, по дефолту
Почему это работает не совсем хорошо:
В 2015 году выходит Go 1.5, в котором изменено стандартное значение
Берется именно то количество ядер, которое доступно ОС, игнорируя
На 24 поточном сервере запускается контейнер с лимитом 1 CPU. Go выставляет
Как это исправить?
Все просто — достаточно прочесть лимит по
TLDR:
Просто используй https://github.com/uber-go/automaxprocs.
За что отвечает GOMAXPORCS:
За количество threads процесса, по дефолту
GOMAXPROCS это количество ядер (потоков) процессора.Почему это работает не совсем хорошо:
В 2015 году выходит Go 1.5, в котором изменено стандартное значение
GOMAXPROCS с 1 на количество ядер (или потоков, если используется HTT). То есть до Go 1.5 создавался только один thread, даже когда приложение запускалось на многоядерных системах. Выставление GOMAXPROCS по количеству ядер позволило ускорить Go в разы.Берется именно то количество ядер, которое доступно ОС, игнорируя
cgroup (в Linux через sched_getaffinity). В этом и заключается проблема.На 24 поточном сервере запускается контейнер с лимитом 1 CPU. Go выставляет
GOMAXPROCS == 24, и создает 24 threads, из-за чего происходит деградация производительности. В самом репозитории есть сравнительная таблица.Как это исправить?
Все просто — достаточно прочесть лимит по
cgroup и если он есть, выставить его через runtime.GOMAXPROCS. Как раз uber-go/automaxprocs этим и занимается.✍10🔥6👾3💅2❤1
Наконец-то выбрался из леса, а это значит, что скоро будут новые посты
🥰6🔥4🏆4💅2👏1🕊1
Небольшой интересный факт о gRPC.
При реализации gRPC сервера, нельзя указать в приложении алгоритм сжатия отправляемого сообщения.
Алгоритм сжатия берется из заголовка запроса
То есть алгоритм сжатия определяет клиент.
При реализации gRPC сервера, нельзя указать в приложении алгоритм сжатия отправляемого сообщения.
Алгоритм сжатия берется из заголовка запроса
grpc-encoding (документация) (код).То есть алгоритм сжатия определяет клиент.
😱5✍4🤓3💅1
Мебибайты и кибибайты.
Меня достаточно давно смущало:
Приставки из СИ (Système international) это степени числа 10
То есть:
10^3 это кило
10^6 это мега
Но когда мы говорим про 1 килобайт, мы говорим про 1024 байт, а не про 1000 байт.
К примеру — код pprof, в исходном коде Go:
И вот, некоторая путаница cуществует с 60-х годов
— Понятия бит введено в 1948 году ( A Mathematical Theory of Communication ).
— В 1950 впервые используется приставка кило для бит, в качестве 1000 бит.
— В 1964 использование приставки K в качестве степени 2 ( A Time-Shared Computer for Real-Time Information Processing ).
Для решения этой путаницы в августе 1995 года добавляют новые приставки, которых нет в СИ:
В вики указан 1998, это когда МЭК ввел
Которые уже обозначают степени числа 2 (2^10, 2^20...).
То есть:
В итоге: спустя 30 лет, после появления приставок степени двойки, путаницы еще больше, уже в течении 60 лет (!!!).
— Проводник в Windows показывает размер в KB, когда на самом деле KiB.
— Внутри Go где-то правильное использование приставок, а где-то нет.
— Приложения GNU вроде (не все проверял) корректно дружат (parted, ls).
— Grafana знает про приставки степени двойки.
— Международное бюро мер и весов (создатели СИ) в брошюре 2019 года написали о том что: приставки СИ сугубо степени числа 10, а приставки степени числа 2 это не СИ не стоит их путать.
Меня достаточно давно смущало:
Приставки из СИ (Système international) это степени числа 10
То есть:
10^3 это кило
10^6 это мега
Но когда мы говорим про 1 килобайт, мы говорим про 1024 байт, а не про 1000 байт.
К примеру — код pprof, в исходном коде Go:
{"kB", []string{"kb", "kbyte", "kilobyte"}, float64(1 << 10)}И вот, некоторая путаница cуществует с 60-х годов
— В 1950 впервые
— В 1964 использование приставки K в качестве степени 2 (
Для решения этой путаницы в августе 1995 года добавляют новые приставки, которых нет в СИ:
kibi (Ki), mebi (Mi), gibi (Gi) and tebi (Ti)
Которые уже обозначают степени числа 2 (2^10, 2^20...).
То есть:
14 КB (килобайт) = 14*10^3 = 14_000 байт
14 KiB (кибибайт) = 14*2^10 = 14_336 байт
В итоге: спустя 30 лет, после появления приставок степени двойки, путаницы еще больше, уже в течении 60 лет (!!!).
— Проводник в Windows показывает размер в KB, когда на самом деле KiB.
— Внутри Go где-то правильное использование приставок, а где-то нет.
— Приложения GNU вроде (не все проверял) корректно дружат (parted, ls).
— Grafana знает про приставки степени двойки.
— Международное бюро мер и весов (создатели СИ) в брошюре 2019 года написали о том что: приставки СИ сугубо степени числа 10, а приставки степени числа 2 это не СИ не стоит их путать.
💅3✍2🐳2
Кажется что в Go скоро появятся новые директивы:
Они будут нужны для новой миграционной тулзы:
На сколько я понял:
А c
К примеру:
Меняется на:
Как по мне, выглядит несколько странно.
P.S.
Не совсем понятно как будет решаться проблема с пересечением скоупа.
Кажется тогда код с которым осуществляется работа может стать максимально некрасивым :с
//go:fix inline
//go:fix forward
Они будут нужны для новой миграционной тулзы:
go fix, которая переписывает на новый API после обновления Go (подробнее можно почитать тут).На сколько я понял:
//go:fix forward — просто меняет обратно совместимую сущность.А c
//go:fix inline чуть муторнее, go fix будет просто инлайнить тело функцииК примеру:
package a
func f() {
One() // want `inline call of a.One`
new(T).Two() // want `inline call of \(a.T\).Two`
}
type T struct{}
//go:fix inline
func One() int { return one } // want One:`goFixInline a.One`
const one = 1
//go:fix inline
func (T) Two() int { return 2 } // want Two:`goFixInline \(a.T\).Two`
Меняется на:
package a
func f() {
_ = one // want `inline call of a.One`
_ = 2 // want `inline call of \(a.T\).Two`
}
type T struct{}
//go:fix inline
func One() int { return one } // want One:`goFixInline a.One`
const one = 1
//go:fix inline
func (T) Two() int { return 2 } // want Two:`goFixInline \(a.T\).Two`
Как по мне, выглядит несколько странно.
P.S.
Не совсем понятно как будет решаться проблема с пересечением скоупа.
Кажется тогда код с которым осуществляется работа может стать максимально некрасивым :с
GitHub
cmd/fix: automate migrations for simple deprecations · Issue #32816 · golang/go
(I've mentioned this in passing on #32014 and #27248, but I don't see an actual proposal filed yet — so here it is!) Over time, the author of a package may notice certain patterns in the us...
👍4✍1❤1👨💻1👀1💅1👾1
Является ли число Pi корректным destination для ping?
PI=3.14159265 ping ${PI}
PI=3.14159265 ping ${PI}
Anonymous Quiz
62%
✅ Да
38%
❌ Нет
🤨3🍌1💅1👾1
Постом выше спрашивал про
А вот и ответ:
🥁🥁🥁
Число
Почему?
Ping использует функцию inet_aton().
И man, говорит про эту функцию следующее:
В итоге, пингануть
🤯 🤯 🤯
Откуда это все пошло:
- 1983,
- 1990,
- 1999,
- 2004,
- 2005,
- 2020,
ping.А вот и ответ:
🥁🥁🥁
Число
Pi для команды ping является корректным аргументом.Почему?
Ping использует функцию inet_aton().
И man, говорит про эту функцию следующее:
a.b.c.d
Each of the four numeric parts specifies a byte of the address; the bytes are assigned in left-to-right order to produce the binary address.
a.b.c
Parts a and b specify the first two bytes of the binary address. Part c is interpreted as a 16-bit value that defines the rightmost two bytes of the binary address. This notation is suitable for specifying (outmoded) Class B network addresses.
a.b
Part a specifies the first byte of the binary address. Part b is interpreted as a 24-bit value that defines the rightmost three bytes of the binary address. This notation is suitable for specifying (outmoded) Class C network addresses.
a
The value a is interpreted as a 32-bit value that is stored directly into the binary address without any byte rearrangement.
В итоге, пингануть
127.0.0.1 можно просто через ping 127.1 или через 0x7F.1, или через 2130706433...Откуда это все пошло:
- 1983,
4.2BSD. Первое появление подобной логики, в функции inet_addr().- 1990,
4.3BSD-Reno. Появление функции inet_aton().- 1999,
Networking Services (XNS) Issue 5.2. Описывает inet_addr(), с подобным синтаксисом.- 2004,
POSIX. Взятое из XNS ассоциация IEEE добавляет в POSIX функции: inet_addr(), inet_ntoa(), сохраняя поведение (link, и через поиск этих функций).- 2005,
RFC 3986, Запрещает подобный синтаксис для URI, хотя в chromium based браузерах оно работает http://2915189091 (ссылка не работает на этом тексте, так что только через ^c ^v).- 2020,
Golang. Создано issue с предложением добавить описанную выше логику в пакет net, спустя почти пять лет (4 декабря 2024) закрывают issue как "not planned".Please open Telegram to view this post
VIEW IN TELEGRAM
✍3👍2🔥2👾2❤🔥1😁1😱1💅1
Please open Telegram to view this post
VIEW IN TELEGRAM
go.dev
Go 1.24 Release Notes - The Go Programming Language
🔥10👏3❤1✍1👌1💅1