Hypothes.is
Небольшой оффтопик про чтение статей. Нашел прикольный инструмент, который позволяет делать аннотации и хайлайты в статьях и, что ещё более удобно, в PDF-файлах.
Очень актуально, когда нужно в чем-то разобраться, источников несколько (например, в случае выше — блог-пост, спецификация, ещё несколько статей) и понимание приходится складывать по кусочкам :)
Небольшой оффтопик про чтение статей. Нашел прикольный инструмент, который позволяет делать аннотации и хайлайты в статьях и, что ещё более удобно, в PDF-файлах.
Очень актуально, когда нужно в чем-то разобраться, источников несколько (например, в случае выше — блог-пост, спецификация, ещё несколько статей) и понимание приходится складывать по кусочкам :)
👍2
Go Time!
Go Time — классный подкаст, посвященный Go и всему, что с ним связано. Иногда приходят даже члены Go Team и участвуют в AMA (ask me anything) сессиях.
Один из самых интересных эпизодов — Creating the Go Programming Language с участием Роба Пайка и Роберта Гризмера.
Мне не так легко в плане концентрации даются длинные подкасты, но, к счастью, у Go Time для каждого эпизода есть транскрипт.
Например, эпизод про создание Go можно не слушать, а прочитать здесь.
Помимо прочего, это ещё и отличная возможность начать активно слушать об интересной для себя тематике на английском. Все непонятное и "нерасслышанное" можно подсмотреть в скрипте и разобрать, если неизвестен перевод или правильное произношение.
Уже за несколько эпизодов можно сильно поднять как свой "технический" английский, так и восприятие на слух — а это очень пригодится на собеседовании, например. В общем, win-win.
Приятного прослушивания и чтения :)
Go Time — классный подкаст, посвященный Go и всему, что с ним связано. Иногда приходят даже члены Go Team и участвуют в AMA (ask me anything) сессиях.
Один из самых интересных эпизодов — Creating the Go Programming Language с участием Роба Пайка и Роберта Гризмера.
Мне не так легко в плане концентрации даются длинные подкасты, но, к счастью, у Go Time для каждого эпизода есть транскрипт.
Например, эпизод про создание Go можно не слушать, а прочитать здесь.
Помимо прочего, это ещё и отличная возможность начать активно слушать об интересной для себя тематике на английском. Все непонятное и "нерасслышанное" можно подсмотреть в скрипте и разобрать, если неизвестен перевод или правильное произношение.
Уже за несколько эпизодов можно сильно поднять как свой "технический" английский, так и восприятие на слух — а это очень пригодится на собеседовании, например. В общем, win-win.
Приятного прослушивания и чтения :)
Что ты за тип?
"Если неучил физику в школе читал спецификацию Go, вся жизнь будет наполнена чудесами и волшебством"
Как это обычно бывает, ответ можно найти в Go Spec/Effective Go/Go FAQ. На этот раз — в последнем:
Несмотря на то, что в compile-time и так происходит проверка на реализацию нужного интерфейса, можно сделать это и самостоятельно при желании.
В примере выше происходит явная проверка на то, что типы
При этом помним, что вторая проверка с
Таким образом:
Можно было бы ещё реализовать проверку так:
Eli Bendersky пишет, если кратко, что смысла в этом не так много, но подобный трюк может пригодиться, если нужно в конкретном участке кода получить ошибку компиляции, если каким-то образом изменится сам интерфейс.
Также Eli напоминает про возможность runtime-проверки:
"Если не
var _ Fooer = (*Foo)(nil)
Строчка кода выше, если особо не задумываться, не кажется очень осмысленной. Blank identifier, nil
, конвертирование типа — сразу несколько финтов, но ради чего? Как это обычно бывает, ответ можно найти в Go Spec/Effective Go/Go FAQ. На этот раз — в последнем:
You can ask the compiler to check that the type T implements the interface I by attempting an assignment using the zero value for T or pointer to T, as appropriate:
type T struct{}
var _ I = T{} // Verify that T implements I.
var _ I = (*T)(nil) // Verify that *T implements I.
Несмотря на то, что в compile-time и так происходит проверка на реализацию нужного интерфейса, можно сделать это и самостоятельно при желании.
В примере выше происходит явная проверка на то, что типы
T
и *T
реализуют интерфейс I
. При этом помним, что вторая проверка с
(*T)(nil)
сильнее: она точно окажется успешной, если T
реализует интерфейс I
. Обратное — неверно (см. пост выше про method sets). Таким образом:
var _ Fooer = (*Foo)(nil)
конвертирует untyped nil
в nil
типа *Foo
и пытается присвоить переменной типа I
. Это, согласно спецификации, возможно, только если method set для конкретного типа в правой части assignment statement шире, чем method set интерфейса. Можно было бы ещё реализовать проверку так:
var _ Fooer = &Foo{}Это, однако, приводит к ненужному в данном случае выделению памяти, поэтому Go FAQ даже их не упоминает.
var _ Fooer = new(Foo)
Eli Bendersky пишет, если кратко, что смысла в этом не так много, но подобный трюк может пригодиться, если нужно в конкретном участке кода получить ошибку компиляции, если каким-то образом изменится сам интерфейс.
Также Eli напоминает про возможность runtime-проверки:
var f FooКонвертирование к типу
_, ok := interface{}(f).(Fooer)
interface{}
(его реализуют все, потому что interface{} says nothing
) нужно, так как type assertions работают только для интерфейсных типов.❤7
Internals of Go
Меня очень впечатлила статья Расса про интерфейсы: с одной стороны, она достаточно подробная, но при этом легко читается и по стилю похожа на аннотированную спецификацию, где техлид проекта пытается объяснить, что и как работает.
Пытался найти что-нибудь подобное для просветления. Вот, что пока удалось найти:
— Golang Internals Resources
Репозиторий с подборкой статей для тех, кто хочет знать, что происходит под капотом
— Go Internals
Незаконченная книга по подкапотным деталям Go. Пока что показалась слишком хардкорной, судя по тому, что первая глава называется "assembly_primer". Надо набраться смелости и когда-нибудь ее все-таки прочитать :)
— Вопрос на SO про изучение внутренностей Go
Отвечаетгосподин Друзь один из самых активных участников SO в Go Language Collective — icza и приводит список must-read статей. Список частично перекликается с репозиторием в первом пункте.
Если есть что-то ещё на примете, кроме статей и видео по ссылкам выше — кидайте, будет круто :)
Меня очень впечатлила статья Расса про интерфейсы: с одной стороны, она достаточно подробная, но при этом легко читается и по стилю похожа на аннотированную спецификацию, где техлид проекта пытается объяснить, что и как работает.
Пытался найти что-нибудь подобное для просветления. Вот, что пока удалось найти:
— Golang Internals Resources
Репозиторий с подборкой статей для тех, кто хочет знать, что происходит под капотом
— Go Internals
Незаконченная книга по подкапотным деталям Go. Пока что показалась слишком хардкорной, судя по тому, что первая глава называется "assembly_primer". Надо набраться смелости и когда-нибудь ее все-таки прочитать :)
— Вопрос на SO про изучение внутренностей Go
Отвечает
Если есть что-то ещё на примете, кроме статей и видео по ссылкам выше — кидайте, будет круто :)
👍8
Go Gotchas
В своём первом посте делился ссылкой на Notion-страничку, где собираю классные ресурсы по Go. Один из блогов в списке — divan.dev, в котором есть неплохие статьи, например, с визуализацией concurrency.
В статье How to Avoid Go Gotchas автор формулирует следующую мысль: большая часть так называемых "gotchas" (грубо говоря, "ловушек") связана с непониманием чего-то фундаментального.
И дальше автор объясняет то, что, на его взгляд, обязательно нужно понимать, чтобы реже удивляться :)
В целом, ничего нового и сложного: указатели, "все передается по значению", слайсы — структура из 3 слов, среди которых указатель на массив, интерфейсы. В общем-то, в постах выше я кратко разбирал соответствующие части спецификации.
Но один момент из статьи, несмотря на простоту, потребовал у меня времени на осознание: то, как работает
Кажется, мой канал можно было смело назвать "Just read the specs" :)
Что такое подходящий размер? Пока размер массива под капотом < 1024, будет выделяться в 2 раза больший массив, но после отметки в 1024 элемента — будет происходить увеличение размера в 1.25 раз.
Почему именно так? Отвечает Роб Пайк:
банан число всего лишь число. Справедливо :)
Во втором случае
Поведение абсолютно понятное, но слегка коварное.
Интересно, что сам автор статьи в одном из примеров то ли опечатался, то ли тоже запутался:
P.S. Кстати, солидно обновил список ресурсов по Go в Notion, если вдруг кто пропустил :)
В своём первом посте делился ссылкой на Notion-страничку, где собираю классные ресурсы по Go. Один из блогов в списке — divan.dev, в котором есть неплохие статьи, например, с визуализацией concurrency.
В статье How to Avoid Go Gotchas автор формулирует следующую мысль: большая часть так называемых "gotchas" (грубо говоря, "ловушек") связана с непониманием чего-то фундаментального.
И дальше автор объясняет то, что, на его взгляд, обязательно нужно понимать, чтобы реже удивляться :)
В целом, ничего нового и сложного: указатели, "все передается по значению", слайсы — структура из 3 слов, среди которых указатель на массив, интерфейсы. В общем-то, в постах выше я кратко разбирал соответствующие части спецификации.
Но один момент из статьи, несмотря на простоту, потребовал у меня времени на осознание: то, как работает
append
и что происходит в результате с копиями слайса. Кажется, мой канал можно было смело назвать "Just read the specs" :)
If the capacity of s is not large enough to fit the additional values, append allocates a new, sufficiently large underlying array that fits both the existing slice elements and the additional values. Otherwise, append re-uses the underlying array.Все просто: если
len(slice) + len(data) > cap(slice)
, выделяется новый underlying-массив подходящего размера, готовый вместить в себя старые + новые элементы. Что такое подходящий размер? Пока размер массива под капотом < 1024, будет выделяться в 2 раза больший массив, но после отметки в 1024 элемента — будет происходить увеличение размера в 1.25 раз.
Почему именно так? Отвечает Роб Пайк:
You need to pick something.Иногда
It was just arbitrary, I'm sure. 1024 is a nice number, and it's larger than the length of many slices.
Sometimes a number is just a number.
Append
(немного) хитёр:func main() {После таких нехитрых манипуляций получим:
s := make([]int, 0, 5)
s = append(s, []int{1, 2, 3, 4}...)
a := append(s, 5)
fmt.Println(a)
b := append(s, 6)
fmt.Println(b)
fmt.Println(a)
}
[1 2 3 4 5]С другой стороны, если поменять
[1 2 3 4 6]
[1 2 3 4 6]
s := make([]int, 0, 5)
на s := make([]int, 0, 4)
, получим:[1 2 3 4 5]Фрагмент из спецификации все объясняет: если capacity слайса хватает, исходный underlying-массив будет переиспользован, что и происходит в первом случае, где
[1 2 3 4 6]
[1 2 3 4 5]
capacity = 5
. Во втором случае
capacity = 4
, что меньше len(slice) + len(data) = 4 + 1 = 5
. В результате выделяется новый кусок памяти под массив для 8 элементов, а len
и cap
нового слайса принимают значения 5 и 8 (то самое удвоение), соответственно. Поведение абсолютно понятное, но слегка коварное.
Интересно, что сам автор статьи в одном из примеров то ли опечатался, то ли тоже запутался:
a := make([]int, 32)Иллюстрация под кодом говорит о том, что
b := a[1:16]
a = append(a, 1)
a[2] = 42
len(b) = cap(b) = 15
, но на самом деле: len(b) = 15, cap(b) = 31
. P.S. Кстати, солидно обновил список ресурсов по Go в Notion, если вдруг кто пропустил :)
🔥6👍4
Alias declaration vs type definition
Идем за разъяснениями в спецификацию:
С другой стороны:
В примере выше
Таким образом, есть две формы декларации типа (type declaration):
1) Декларация алиаса (alias declaration)
2) Определение типа (type definition)
Синтаксически они отличаются лишь знаком равенства, но никакого смыслового равенства нет.
И остается один вопрос: зачем вообще использовать type aliases?
Обращаемся к выступлению Расса под названием "Codebase Refactoring (with help from Go)", где написано:
type Test = stringЕсли присмотреться, можно заметить, что это все-таки 2 разные строки :) При этом первая выглядит достаточно непривычно, в то время как вторая — конструкция, знакомая и понятная.
type Test string
Идем за разъяснениями в спецификацию:
Alias declarationsСогласно спецификации,
An alias declaration binds an identifier to the given type.
Within the scope of the identifier, it serves as an alias for the type.
type (
nodeList = []*Node // nodeList and []*Node are identical types
Polar = polar // Polar and polar denote identical types
)
Polar
и polar
— один и тот же тип, мы всего лишь создали "алиас".С другой стороны:
A type definition creates a new, distinct type with the same underlying type and operations as the given type, and binds an identifier to it.В случае с type definition мы объявляем новый тип (defined type), на основе выбранного underlying type.
The new type is called a defined type. It is different from any other type, including the type it is created from.
type (
Point struct{ x, y float64 } // Point and struct{ x, y float64 } are different types
polar Point // polar and Point denote different types
)
В примере выше
polar
— defined type, Point
— underlying type.Таким образом, есть две формы декларации типа (type declaration):
1) Декларация алиаса (alias declaration)
2) Определение типа (type definition)
Синтаксически они отличаются лишь знаком равенства, но никакого смыслового равенства нет.
И остается один вопрос: зачем вообще использовать type aliases?
Обращаемся к выступлению Расса под названием "Codebase Refactoring (with help from Go)", где написано:
5.3. Type aliasesЕсли подытожить: это явно не то, чем придется регулярно пользоваться, но такой синтаксический финт может пригодиться во время масштабного рефакторинга кодовой базы.
To enable gradual code repair during codebase refactorings, it must be possible to create alternate names for a constant, function, variable, or type. Go already allows introducing alternate names for all constants, all functions, and nearly all variables, but no types. Put another way, the general alias form is never necessary for constants, never necessary for functions, only rarely necessary for variables, but always necessary for types.
type OldAPI = NewPackage.API
👍3
Maps in Go
Map — структура данных, которая важна сразу по нескольким причинам: с одной стороны, — это классическая структура данных, без которой сложно представить программирование, и, с другой, само ее устройство может стать предметом разговора на собеседовании (вопрос популярный, проверено).
Устроена она несколько сложнее, чем массивы (константную сложность надо заслужить), но это все ещё не rocket science, если не вдаваться в криптографию.
Вероятно, это не самая точная аналогия, но будем для простоты терминологии называть
В Go этот "интерфейс" реализован как
Согласно Go FAQ, реализация настолько хороша, что в большинстве случаев о ней не придется задумываться:
Сначала заметим, что
Это стоит иметь в виду, и об этом предупреждает Effective Go:
Очень рекомендую статью Dave Cheney про устройство `map`. В ней рассказано:
— Про саму структуру данных без привязки к какому-либо языку
— В каком виде
— Какие есть нюансы реализации в самом Go: например, при их реализации обошлись без дженериков,
Если нужно для собеседований или по какой-то другой причине глубже разобраться в структурах данных и основах теории сложности алгоритмов (все эти о-малые, О-большие, теты и омеги), могу порекомендовать книгу Скиены — Algorithm Design Manual. Как по мне, идеальный баланс между теорией и практикой.
Map — структура данных, которая важна сразу по нескольким причинам: с одной стороны, — это классическая структура данных, без которой сложно представить программирование, и, с другой, само ее устройство может стать предметом разговора на собеседовании (вопрос популярный, проверено).
Устроена она несколько сложнее, чем массивы (константную сложность надо заслужить), но это все ещё не rocket science, если не вдаваться в криптографию.
Вероятно, это не самая точная аналогия, но будем для простоты терминологии называть
map
—своего рода "интерфейсом", который определяет нужное для нас поведение и свойство: O(1) lookups
(то есть, доступ по ключу) в среднем (это значит, что может быть и хуже, если выбранная хеш-функция звезд с неба не хватает). В Go этот "интерфейс" реализован как
hashmap
. Эта структура данных используется в Go рантайме. Согласно Go FAQ, реализация настолько хороша, что в большинстве случаев о ней не придется задумываться:
The same reason strings are: they are such a powerful and important data structure that providing one excellent implementation with syntactic support makes programming more pleasant. We believe that Go's implementation of maps is strong enough that it will serve for the vast majority of uses.Но это нас не остановит, конечно же.
Сначала заметим, что
map
в Go — это указатель на runtime.hmap
. Иначе говоря, это так называемый reference/reference type
, но никакого pass by reference по-прежнему нет: копируется указатель, а не сами данные. Это стоит иметь в виду, и об этом предупреждает Effective Go:
Like slices, maps hold references to an underlying data structure. If you pass a map to a function that changes the contents of the map, the changes will be visible in the caller.Кстати, когда-то вместо
map[K]V
предполагалось использовать *map[K]V
, но потом, как пишет Ian Lance Taylor, стало ясно, что приходится всегда писать *map
, это нудно, и поэтому синтаксис упростили. Очень рекомендую статью Dave Cheney про устройство `map`. В ней рассказано:
— Про саму структуру данных без привязки к какому-либо языку
— В каком виде
map
присутствует в ряде популярных языков— Какие есть нюансы реализации в самом Go: например, при их реализации обошлись без дженериков,
interface{}
и кодогенерации Если нужно для собеседований или по какой-то другой причине глубже разобраться в структурах данных и основах теории сложности алгоритмов (все эти о-малые, О-большие, теты и омеги), могу порекомендовать книгу Скиены — Algorithm Design Manual. Как по мне, идеальный баланс между теорией и практикой.
👍7
Maps in Go (addendum)
Кстати, в статье Dave Cheney есть один момент, который меня немного смущает.
В примерах применения хеш-функции говорится о "masking off the lower 3 bits", что по сути означает (должно означать в моем понимании) операцию
Возможно, речь о чем-то другом и тогда буду благодарен, если кто-то в комментариях разъяснит :)
Кстати, в статье Dave Cheney есть один момент, который меня немного смущает.
В примерах применения хеш-функции говорится о "masking off the lower 3 bits", что по сути означает (должно означать в моем понимании) операцию
AND
с 111
, но полученные номера бакетов почему-то не соответствуют такой логике (см. примеры из статьи). Возможно, речь о чем-то другом и тогда буду благодарен, если кто-то в комментариях разъяснит :)
Ресурсы по БД
Небольшой оффтоп, посвященный БД с некоторым (думаю, понятным) перекосом в пользу PostgreSQL.
Скажу банальность: SQL — lingua franca для всех, кто работает с данными, поэтому очень полезно понимать не только синтаксис и базовые селекты, которым можно научиться за пару часов, но и более тонкие нюансы.
Ресурсы, которые я когда-либо читал/смотрел (и до сих пор периодически возвращаюсь):
— Фантастический курс по устройству баз данных от CMU
Это не самая новая версия курса, но очень советую слушать именно версию Andy Pavlo. Он потрясающий преподаватель, который обожает то, чем занимается, и это чувствуется. Содержание курса тоже 🔥
На сайте доступны слайды и конспекты по курсу.
— По самому PostgreSQL, кажется, нет ничего лучше, чем официальная документация. Можно начать с туториала, и дальше использовать уже в качестве справочника. Написано очень подробно и доступно.
— В документации очень подробная глава про индексы, их разновидности и применение, но самый классный ресурс на тему производительности и использования индексов в частности — Use the Index, Luke!. Незаменимый ресурс, если нужно разобраться в использовании индексов на практике.
— Мини-книжка по SQL optimization от Dataschool. Можно прочитать ее до Use the Index, Luke, чтобы сразу быть в контексте. Но тут без особой глубины.
— Попрактиковаться очень удобно на PostgreSQL Exercises. Каждая задача сопровождается чуть ли не построчным объяснением. Классный формат, совмещающий теорию и практику.
— Оконные функции считаются (не уверен, что по праву) своего рода инициацией в advanced-зону, поэтому стоит один раз в них разобраться и набить руку. Это можно сделать на специальном сайте, который и теорию объяснит, и задачки подкинет.
— И наконец хардкор. Зубодробительные внутренности PostgreSQL, где автор предполагает, что его целевая аудитория — администраторы БД. Начал читать, но, по правде говоря, это та книга, которую точно лучше использовать как справочник. Захотелось узнать, как обрабатываются запросы в любимом PG — открыли третью главу, разобрались,на следующий день все забыли.
Небольшой оффтоп, посвященный БД с некоторым (думаю, понятным) перекосом в пользу PostgreSQL.
Скажу банальность: SQL — lingua franca для всех, кто работает с данными, поэтому очень полезно понимать не только синтаксис и базовые селекты, которым можно научиться за пару часов, но и более тонкие нюансы.
Ресурсы, которые я когда-либо читал/смотрел (и до сих пор периодически возвращаюсь):
— Фантастический курс по устройству баз данных от CMU
Это не самая новая версия курса, но очень советую слушать именно версию Andy Pavlo. Он потрясающий преподаватель, который обожает то, чем занимается, и это чувствуется. Содержание курса тоже 🔥
На сайте доступны слайды и конспекты по курсу.
— По самому PostgreSQL, кажется, нет ничего лучше, чем официальная документация. Можно начать с туториала, и дальше использовать уже в качестве справочника. Написано очень подробно и доступно.
— В документации очень подробная глава про индексы, их разновидности и применение, но самый классный ресурс на тему производительности и использования индексов в частности — Use the Index, Luke!. Незаменимый ресурс, если нужно разобраться в использовании индексов на практике.
— Мини-книжка по SQL optimization от Dataschool. Можно прочитать ее до Use the Index, Luke, чтобы сразу быть в контексте. Но тут без особой глубины.
— Попрактиковаться очень удобно на PostgreSQL Exercises. Каждая задача сопровождается чуть ли не построчным объяснением. Классный формат, совмещающий теорию и практику.
— Оконные функции считаются (не уверен, что по праву) своего рода инициацией в advanced-зону, поэтому стоит один раз в них разобраться и набить руку. Это можно сделать на специальном сайте, который и теорию объяснит, и задачки подкинет.
— И наконец хардкор. Зубодробительные внутренности PostgreSQL, где автор предполагает, что его целевая аудитория — администраторы БД. Начал читать, но, по правде говоря, это та книга, которую точно лучше использовать как справочник. Захотелось узнать, как обрабатываются запросы в любимом PG — открыли третью главу, разобрались,
🔥11👍1
Distributed Systems
Продолжаем рубрику "я и моя нездоровая любовь к спискам".
На этот раз — список для изучения system design/scalability/distributed systems (в общем, путь в Google). Как мог сказать бы в наше время Ломоносов: "System design уже затем учить надо, что он ум в порядок приводит".
Область огромная, непростая, но очень интересная. К тому же, если вдруг придется проходить собеседования в FAANG (или похожие компании с многоэтапными собеседованиями), эти знания очень пригодятся.
— Нельзяпросто так взять и не начать с Designing Data-Intensive Applications aka "кабанчика". Эта книга Мартина Клеппемана — одна из самых часто рекомендуемых книг в области IT в целом, но дело не в популярности, а в том какая она крутая. Постоянно к ней возвращаюсь и понимаю по-новому по мере обретения опыта :)
— Мартин Клеппеман не так давно выложил ещё и свой курс по распределенным системам, который читает в Кембридже. Во многом лекции перекликаются с книгой, но есть также и видеозаписи, которые могут понравиться тем, кто лучше усваивает информацию из видео :)
— System Design Primer
Невероятно крутой репозиторий с джентльменским набором знаний в области system design. Уступает, конечно, в глубине книгам, но для собеседования или понимания в общих чертах просто идеально.
— Web-Scalability for Startup Engineers
Менее известная, но тоже замечательная книга, которая объясняет system design от лица стартапа, который по мере роста сталкивается с необходимостью масштабироваться.
— The Architecture of Open Source Applications
Основы распределенных систем с реальными примерами в open source мире.
— Distributed Systems for Fun and Profit
Небольшая, но классная книга, с которой можно начать.
— MIT: 6.824 Distributed Systems
Крутой курс от MIT, который, кстати, использует Go. Всегда хотел его посмотреть до конца, но видео мне даются тяжело, поэтому в основном читаю, а видео смотрю лишь эпизодически.
— Пост Robert Heaton с практичным введением в system design. Захватывающая проза с шутками и историями из жизни.
— Похожий пост от Gergely Orocz про основные понятия из system design, которые автору пришлось усвоить во время работы над платежной системой: SLA, идемпотентность — все на месте :)
— Highscalability
Блог с разбором архитектур реальных высоконагруженных сервисов.
Продолжаем рубрику "я и моя нездоровая любовь к спискам".
На этот раз — список для изучения system design/scalability/distributed systems (в общем, путь в Google). Как мог сказать бы в наше время Ломоносов: "System design уже затем учить надо, что он ум в порядок приводит".
Область огромная, непростая, но очень интересная. К тому же, если вдруг придется проходить собеседования в FAANG (или похожие компании с многоэтапными собеседованиями), эти знания очень пригодятся.
— Нельзя
— Мартин Клеппеман не так давно выложил ещё и свой курс по распределенным системам, который читает в Кембридже. Во многом лекции перекликаются с книгой, но есть также и видеозаписи, которые могут понравиться тем, кто лучше усваивает информацию из видео :)
— System Design Primer
Невероятно крутой репозиторий с джентльменским набором знаний в области system design. Уступает, конечно, в глубине книгам, но для собеседования или понимания в общих чертах просто идеально.
— Web-Scalability for Startup Engineers
Менее известная, но тоже замечательная книга, которая объясняет system design от лица стартапа, который по мере роста сталкивается с необходимостью масштабироваться.
— The Architecture of Open Source Applications
Основы распределенных систем с реальными примерами в open source мире.
— Distributed Systems for Fun and Profit
Небольшая, но классная книга, с которой можно начать.
— MIT: 6.824 Distributed Systems
Крутой курс от MIT, который, кстати, использует Go. Всегда хотел его посмотреть до конца, но видео мне даются тяжело, поэтому в основном читаю, а видео смотрю лишь эпизодически.
— Пост Robert Heaton с практичным введением в system design. Захватывающая проза с шутками и историями из жизни.
— Похожий пост от Gergely Orocz про основные понятия из system design, которые автору пришлось усвоить во время работы над платежной системой: SLA, идемпотентность — все на месте :)
— Highscalability
Блог с разбором архитектур реальных высоконагруженных сервисов.
🔥12
Rethinking Classical Concurrency Patterns
Иду по официальному списку для изучения concurrency in Go. Цель — добиться того, чтобы не только понимать уже написанный код, но и понимать, как писать конкурентный код на Go грамотно и эффективно и, что не менее важно, понимать, когда его писать не надо (какой-то Воннегут получился).
Один из пунктов списка — очень крутое выступление Bryan Mills (работает над Go) про concurrency patterns.
Слушать Брайана — одно удовольствие, но можно и почитать слайды с подробной расшифровкой речи.
Хорошего воскресенья :)
Иду по официальному списку для изучения concurrency in Go. Цель — добиться того, чтобы не только понимать уже написанный код, но и понимать, как писать конкурентный код на Go грамотно и эффективно и, что не менее важно, понимать, когда его писать не надо (какой-то Воннегут получился).
Один из пунктов списка — очень крутое выступление Bryan Mills (работает над Go) про concurrency patterns.
Слушать Брайана — одно удовольствие, но можно и почитать слайды с подробной расшифровкой речи.
Хорошего воскресенья :)
🔥7
Allocations in Go
Всегда чувствую некоторый дискомфорт, когда в обсуждении речь заходит о стеке, куче и выделении памяти. С одной стороны, кажется, что это должно быть важно с точки зрения производительности, но при этом Effective Go, например, даже не упоминает ничего про стек и кучу, помимо одной строчки в разделе про горутины.
На самом деле, согласно Go FAQ:
— С точки зрения корректности, знать о том, где создаются переменные, не нужно. До тех пор, пока кто-то на эти переменные ссылается, они будут существовать. Где именно создаются переменные, — не важно с точки зрения семантики языка (и это даже не упоминается в спецификации)
— И все же есть некоторые обобщенные правила: если у переменной берется адрес, она становится кандидатом для выделения в куче. Если компилятору очевидно, что никаких референсов к переменной не будет после выхода из функции, переменная будет выделена в стековом фрейме функции. В противном случае — переменная будет создана в куче.
Даже из самих формулировок следует, что никаких гарантий и четких правил для каждого случая нет.
Более детально можно почитать здесь:
— Understanding Allocations in Go (+ полезные ссылки в конце статьи)
— Интересное обсуждение на Stackoverflow
Всегда чувствую некоторый дискомфорт, когда в обсуждении речь заходит о стеке, куче и выделении памяти. С одной стороны, кажется, что это должно быть важно с точки зрения производительности, но при этом Effective Go, например, даже не упоминает ничего про стек и кучу, помимо одной строчки в разделе про горутины.
На самом деле, согласно Go FAQ:
— С точки зрения корректности, знать о том, где создаются переменные, не нужно. До тех пор, пока кто-то на эти переменные ссылается, они будут существовать. Где именно создаются переменные, — не важно с точки зрения семантики языка (и это даже не упоминается в спецификации)
— И все же есть некоторые обобщенные правила: если у переменной берется адрес, она становится кандидатом для выделения в куче. Если компилятору очевидно, что никаких референсов к переменной не будет после выхода из функции, переменная будет выделена в стековом фрейме функции. В противном случае — переменная будет создана в куче.
Даже из самих формулировок следует, что никаких гарантий и четких правил для каждого случая нет.
Более детально можно почитать здесь:
— Understanding Allocations in Go (+ полезные ссылки в конце статьи)
— Интересное обсуждение на Stackoverflow
Are you a Go Black Belt?
John Arundel пишет книги и делает курсы по Go, менторит, а также руководит компанией Bitfield Consulting.
В своей статье Джон отходит от традиционных уровней junior-middle-senior (и похожие вариации) знаний и предлагает иную, заимствованную из боевых искусств систему с поясами.
По мнению Джона, в зависимости от ширины и глубины навыков можно условному Go-студенту присвоить один из поясов в диапазоне от белого до черного :)
При этом понятно, что это всего лишь очень грубый способ оценить свои текущие знания, некий ориентир, не более того. К сожалению, мы не так уж хорошо способны оценить как масштаб своего знания, так и незнания :)
John Arundel пишет книги и делает курсы по Go, менторит, а также руководит компанией Bitfield Consulting.
В своей статье Джон отходит от традиционных уровней junior-middle-senior (и похожие вариации) знаний и предлагает иную, заимствованную из боевых искусств систему с поясами.
По мнению Джона, в зависимости от ширины и глубины навыков можно условному Go-студенту присвоить один из поясов в диапазоне от белого до черного :)
При этом понятно, что это всего лишь очень грубый способ оценить свои текущие знания, некий ориентир, не более того. К сожалению, мы не так уж хорошо способны оценить как масштаб своего знания, так и незнания :)
Embedded Fields and Methods
Как меняются наборы методов типа (method sets) в случае с "вложениями" (embedded fields)?
Читаем спецификацию и разбираемся:
— Если
— Если
— Как мы уже привыкли, в случае с методами на конкретных типах компилятор способен понять и простить нас за нежелание думать о method sets: можем вызвать как
— В случае с интерфейсами вседозволенность заканчивается: пример выше не скомпилится с предупреждением о том, что
И мы можем, согласно спецификации, либо переписывать assignment на
Как меняются наборы методов типа (method sets) в случае с "вложениями" (embedded fields)?
Читаем спецификацию и разбираемся:
Given a struct type S and a defined type T, promoted methods are included in the method set of the struct as follows:Никаких сюрпризов, помимо тех, к которым все уже привыкли:
If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
If S contains an embedded field *T, the method sets of S and *S both include promoted methods with receiver T or *T.
— Если
T
вложен в S
, наборы методов как у S
, так и у *S
содержат методы с ресивером T
. При этом набор методов у *S
традиционно шире и также включает в себя методы с ресивером *T
. — Если
*T
вложен в S
, в наборах методах полное раздолье: как у S
, так и *S
, можно использовать методы, определенные и на T
, и на *T
. type Original struct {Проверить эти нехитрые правила можно на примере выше:
Name string
}
type Copycat struct {
Original
Name string
}
type Greeter interface {
GreetOriginal(s string) string
}
func (o *Original) GreetOriginal(s string) string {
return s + " " + o.Name
}
func (c Copycat) GreetCopycat(s string) string {
return s + " " + c.Name
}
func main() {
t := Copycat{
Original: Original{Name: "Michael"},
Name: "George",
}
fmt.Println(t.GreetOriginal("Hi"))
fmt.Println(t.GreetCopycat("Aloha"))
var s Greeter
s = t
fmt.Println(s.GreetOriginal("Hello"))
}
— Как мы уже привыкли, в случае с методами на конкретных типах компилятор способен понять и простить нас за нежелание думать о method sets: можем вызвать как
GreetOriginal
, так и GreetCopycat
без каких-либо ограничений. — В случае с интерфейсами вседозволенность заканчивается: пример выше не скомпилится с предупреждением о том, что
Copycat
не реализует интерфейс Greeter
, ведь GreetOriginal
определен с указателем. И мы можем, согласно спецификации, либо переписывать assignment на
s = &t
, либо поменять ресивер у GreetOriginal
на Original
, либо вложить *Original
в Copycat
🔥3
Operating Systems
Если вдруг кому-то тоже хочется начать лучше разбираться в том, как работают современные операционные системы, очень рекомендую (бесплатную) книгу Operating Systems: Three Easy Pieces.
В меру подробная и при этом очень легко читается. Отличная альтернатива книгам Танненбаума.
Если вдруг кому-то тоже хочется начать лучше разбираться в том, как работают современные операционные системы, очень рекомендую (бесплатную) книгу Operating Systems: Three Easy Pieces.
В меру подробная и при этом очень легко читается. Отличная альтернатива книгам Танненбаума.
🔥5👍1
Struct equality
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
Во-первых, структуры сравнимы, если все их поля сравнимы. С этим в примере выше порядок: инты и строки сравнимы в привычном смысле.
Интереснее обратить внимание на условие равенства: структуры равны, если все их одноименные поля равны. В нашем примере именованных полей нет вообще, так что условие выполняется автоматически :)
type T struct {Логика подсказывает, что
_ int
_ string
}
func main() {
t1 := T{128, "hey"}
t2 := T{256, "heyhey"}
fmt.Println(t1 == t2)
}
t1
и t2
не равны. Но код выше напечатает true
. Ищем ответ на этот вопрос сами знаете где:Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
Во-первых, структуры сравнимы, если все их поля сравнимы. С этим в примере выше порядок: инты и строки сравнимы в привычном смысле.
Интереснее обратить внимание на условие равенства: структуры равны, если все их одноименные поля равны. В нашем примере именованных полей нет вообще, так что условие выполняется автоматически :)
References in Go
Немного буквоедства: как-то Роб Пайк на Гитхабе попросил в документации отдельно указать, что в Go существуют так называемые references, то есть структуры, которые либо являются указателем, либо его в себе неявно содержат.
Алан Донован (один из авторов той самой книги про Go) считанные минуты назад добавил изменения в документацию (появится в 1.19) с более подробным объяснением возможных подводных камней при копировании таких структур данных.
https://go-review.googlesource.com/c/go/+/391634/
Немного буквоедства: как-то Роб Пайк на Гитхабе попросил в документации отдельно указать, что в Go существуют так называемые references, то есть структуры, которые либо являются указателем, либо его в себе неявно содержат.
Алан Донован (один из авторов той самой книги про Go) считанные минуты назад добавил изменения в документацию (появится в 1.19) с более подробным объяснением возможных подводных камней при копировании таких структур данных.
https://go-review.googlesource.com/c/go/+/391634/
О главном языке в программировании
На вечный вопрос о лучшем языке для новичка в программировании всегда хочется ответить, что это не Python, не Java и даже не Go (скрепя сердцем), а английский язык.
Так уж получилось, что почти все ресурсы по разработке выпускаются на английском и только потом переводятся на другие языки. Переводы часто сильно отстают (пока переводят издание N, выходит издание N+1), а уж перевод документации и вовсе кажется бессмысленным занятием.
Умение/желание читать на английском позволяет ещё и приобщиться к огромному англоязычному сообществу — общаться на Stackoverflow, Hackernews, Reddit, Discord и прочих площадках. Стоит ли говорить, что "гугление" не на английском в нашей сфере почти лишено смысла, а для этого нужно хотя бы немного уметь формулировать на английском.
В конце концов, однажды вас могут перекинуть на англоязычный проект, где придется каждый день общаться — проводить встречи, переписываться в любимом корпоративом мессенджере.
После такого вступления самое время порекомендовать учебный курс по английскому и поделиться промокодом, но не в этот раз. Вместо этого порекомендую ряд классных ресурсов, которые помогут в изучении английского (с небольшим акцентом на письмо).
1. https://ozdic.com/
Предположим, вы пишете сообщение или письмо на английском и хотите написать о чрезвычайной сложности задачи, которую перед вами поставили на текущий спринт. Big difficulty, great difficulty, severe difficulty? Здесь на помощь приходит сервис Ozdic, который на самом деле является онлайн-версией словаря Oxford Collocations Dictionary. Достаточно всего лишь ввести "difficulty" для того, чтобы увидеть кучу примеров использования слова и "коллокаций" (словосочетаний) в связке с другими частями речи. Постоянно пользуюсь сервисом и всячески рекомендую.
2. https://fraze.it/
Проверив на Ozdic, вы выяснили, что enormous difficulty — это ОК, Oxford одобряет. Было бы здорово ещё посмотреть примеры использования в авторитетных источниках (ну, скажем, The Economist). Вводим словосочетание на Fraze.it и видим подборку примеров использования из англоязычных источников, тематические картинки (не очень понятно зачем, но ладно) и, почти самое крутое, подборку роликов на Youtube, где нейтивы произносят указанное слово/словосочетание.
3. https://lengusa.com/
Этот ресурс похож на предыдущий, но позволяет ещё сравнивать частотности употребления слов/словосочетаний, переводить на другие языки, вставлять пропущенное слово.
4. https://www.usingenglish.com/reference/
Классный сервис с богатой подборкой идиом (устойчивых словосочетаний) и фразовых глаголов.
5. https://www.ldoceonline.com/
Мой любимый монолингвальный (с английского на английский) словарь. Я убежден в том, что начинать пользоваться такими словарями нужно практически с самого начала — это позволяет, во-первых, больше читать на английском, избавляться от ненужных параллелей с родным языком и не полагаться на языковые предпочтения (или ещё хуже — заблуждения) составителей билингвальных словарей. Словарь от Longman очень подробный, не игнорирует американский вариант произношения (почти) и разбавляет сухие словарные статьи примерами использования слова в контексте.
6. https://www.merriam-webster.com/
Не менее великий словарь для фанатов AmE. Здесь вас точно не обманут во всем, что связано с американским английским.
7. https://www.multitran.com/
Если все-таки нужно перевести с русского на англиийский, можно использовать Multitran.
8. Last but not least, мой любимый справочник по грамматике английского языка:
https://www.amazon.com/Practical-English-Usage-Michael-Swan/dp/0194420981
Он тоже англоязычный — в случае с грамматикой мне кажется ещё более важным ранний отказ от русскоязычных источников. Справочник Майкла Свона удобен в первую очередь тем, что можно найти проблемную для себя область (например, articles), найти ее и в порядке увеличения сложности материала прочитать практически все об артиклях — от "what are articles" до чрезвычайно каверзных кейсах, в которых ошибаются даже нейтивы.
На вечный вопрос о лучшем языке для новичка в программировании всегда хочется ответить, что это не Python, не Java и даже не Go (скрепя сердцем), а английский язык.
Так уж получилось, что почти все ресурсы по разработке выпускаются на английском и только потом переводятся на другие языки. Переводы часто сильно отстают (пока переводят издание N, выходит издание N+1), а уж перевод документации и вовсе кажется бессмысленным занятием.
Умение/желание читать на английском позволяет ещё и приобщиться к огромному англоязычному сообществу — общаться на Stackoverflow, Hackernews, Reddit, Discord и прочих площадках. Стоит ли говорить, что "гугление" не на английском в нашей сфере почти лишено смысла, а для этого нужно хотя бы немного уметь формулировать на английском.
В конце концов, однажды вас могут перекинуть на англоязычный проект, где придется каждый день общаться — проводить встречи, переписываться в любимом корпоративом мессенджере.
После такого вступления самое время порекомендовать учебный курс по английскому и поделиться промокодом, но не в этот раз. Вместо этого порекомендую ряд классных ресурсов, которые помогут в изучении английского (с небольшим акцентом на письмо).
1. https://ozdic.com/
Предположим, вы пишете сообщение или письмо на английском и хотите написать о чрезвычайной сложности задачи, которую перед вами поставили на текущий спринт. Big difficulty, great difficulty, severe difficulty? Здесь на помощь приходит сервис Ozdic, который на самом деле является онлайн-версией словаря Oxford Collocations Dictionary. Достаточно всего лишь ввести "difficulty" для того, чтобы увидеть кучу примеров использования слова и "коллокаций" (словосочетаний) в связке с другими частями речи. Постоянно пользуюсь сервисом и всячески рекомендую.
2. https://fraze.it/
Проверив на Ozdic, вы выяснили, что enormous difficulty — это ОК, Oxford одобряет. Было бы здорово ещё посмотреть примеры использования в авторитетных источниках (ну, скажем, The Economist). Вводим словосочетание на Fraze.it и видим подборку примеров использования из англоязычных источников, тематические картинки (не очень понятно зачем, но ладно) и, почти самое крутое, подборку роликов на Youtube, где нейтивы произносят указанное слово/словосочетание.
3. https://lengusa.com/
Этот ресурс похож на предыдущий, но позволяет ещё сравнивать частотности употребления слов/словосочетаний, переводить на другие языки, вставлять пропущенное слово.
4. https://www.usingenglish.com/reference/
Классный сервис с богатой подборкой идиом (устойчивых словосочетаний) и фразовых глаголов.
5. https://www.ldoceonline.com/
Мой любимый монолингвальный (с английского на английский) словарь. Я убежден в том, что начинать пользоваться такими словарями нужно практически с самого начала — это позволяет, во-первых, больше читать на английском, избавляться от ненужных параллелей с родным языком и не полагаться на языковые предпочтения (или ещё хуже — заблуждения) составителей билингвальных словарей. Словарь от Longman очень подробный, не игнорирует американский вариант произношения (почти) и разбавляет сухие словарные статьи примерами использования слова в контексте.
6. https://www.merriam-webster.com/
Не менее великий словарь для фанатов AmE. Здесь вас точно не обманут во всем, что связано с американским английским.
7. https://www.multitran.com/
Если все-таки нужно перевести с русского на англиийский, можно использовать Multitran.
8. Last but not least, мой любимый справочник по грамматике английского языка:
https://www.amazon.com/Practical-English-Usage-Michael-Swan/dp/0194420981
Он тоже англоязычный — в случае с грамматикой мне кажется ещё более важным ранний отказ от русскоязычных источников. Справочник Майкла Свона удобен в первую очередь тем, что можно найти проблемную для себя область (например, articles), найти ее и в порядке увеличения сложности материала прочитать практически все об артиклях — от "what are articles" до чрезвычайно каверзных кейсах, в которых ошибаются даже нейтивы.
👍16