Forwarded from Азбука айтишника
🔧 Компилятор своими руками: краткий гид для начинающих
В этой статье мы разберем анатомию простейшего компилятора: лексер, парсер и LLVM. Вы узнаете, как эти компоненты взаимодействуют для преобразования исходного кода в исполняемый файл.
🔗 Ссылка на статью
В этой статье мы разберем анатомию простейшего компилятора: лексер, парсер и LLVM. Вы узнаете, как эти компоненты взаимодействуют для преобразования исходного кода в исполняемый файл.
🔗 Ссылка на статью
👍6🥱3
🛠️💥 Использование Go для всего
Зачем использовать 10 инструментов, если можно освоить один? Познакомьтесь с соло-разработчиком Маркусом, который превратил Go в свой швейцарский армейский нож. От CLI до игр для Nintendo Switch — Go делает все!
👉 Читать
Зачем использовать 10 инструментов, если можно освоить один? Познакомьтесь с соло-разработчиком Маркусом, который превратил Go в свой швейцарский армейский нож. От CLI до игр для Nintendo Switch — Go делает все!
👉 Читать
www.maragu.dev
Go is my hammer, and everything is a nail
Always choose the right tool for the job? Nah. I use Go basically everywhere, which either makes me insightful or stupid. Decide for yourself! :D
👍19😁2💯1
Вы наверняка знакомы со «стандартным» способом ветвления кода в зависимости от заданного значения:
Так работает
Но оператор
1. Несколько значений в одном
В
Заданное значение может использоваться только в одном блоке
2. Инициализатор, как в цикле
Вы можете инициализировать значение перед использованием его в
3. Нет выражения
Если текущее значение
4. Переключение по типу переменной.
Если ваш код получает значение интерфейса из какого-то источника, вы можете использовать переключение по типу, чтобы проверить фактический тип этого значения:
5. Переключение по типу параметра.
Это может показаться немного эзотерическим: вы можете определить дженерик функцию, где типовой параметр не используется в списке параметров. Вместо этого оператор
Как и с выражениями
👉 Go Playground
#tip
switch a {
case 1:
fmt.Println("1")
case 2:
fmt.Println("2")
default:
fmt.Println("default")
}
Так работает
switch
в Go и во многих других языках (за исключением того, что в Go не происходит перехода к последующим case
).Но оператор
switch
может делать больше. Вот несколько кейсов.1. Несколько значений в одном
case
.В
case
можно указать несколько значений для сопоставления:
switch a {
case 1:
fmt.Println("1")
case 2, 3, 4:
fmt.Println("2, 3 или 4")
// case 1,2: // ошибка: дублирование case 1, дублирование case 2
// fmt.Println("1 или 2")
}
Заданное значение может использоваться только в одном блоке
case
. Дублирование значений в case
вызовет ошибку.2. Инициализатор, как в цикле
for
.Вы можете инициализировать значение перед использованием его в
switch
. Область видимости переменной a
ограничена конструкцией switch
:
switch a := f(); a {
case 1:
fmt.Println("1")
case 2:
fmt.Println("2")
}
3. Нет выражения
switch
, но есть выражения case
.case
не ограничен статическими значениями. Если вы опустите выражение switch
, вы можете использовать выражения для каждого case
:
switch {
case a == 1:
fmt.Println("1")
case a >=2 && a <= 4:
fmt.Println("2")
case a <= 5:
fmt.Println("3")
}
Если текущее значение
a
совпадает более чем с одним case
, выбирается первый подходящий.4. Переключение по типу переменной.
Если ваш код получает значение интерфейса из какого-то источника, вы можете использовать переключение по типу, чтобы проверить фактический тип этого значения:
switch v := a.(type) {
case int:
fmt.Println("a — это int:", v)
case string, []byte:
fmt.Println("a — это string:", v)
}
5. Переключение по типу параметра.
Это может показаться немного эзотерическим: вы можете определить дженерик функцию, где типовой параметр не используется в списке параметров. Вместо этого оператор
switch
может ссылаться на этот параметр, чтобы проверить значение параметра:
func do[T comparable](a any) {
switch v := a.(type) {
case int:
fmt.Println("a — это int:", v)
case T:
fmt.Printf("a — это %T: %v", v, v)
case []T:
fmt.Println("a — это срез:", v)
case []byte:
fmt.Println("a — это срез байт:", v)
}
}
func main() {
do[bool](a)
do[bool](true)
do[int]([]int{1, 2, 3})
}
Как и с выражениями
case
, если фактический тип a
совпадает с несколькими case
, выбирается первый подходящий.👉 Go Playground
#tip
go.dev
Go Playground - The Go Programming Language
👍60❤7🥱5🔥3😍1
❗Вакансии «Библиотеки программиста» — ждем вас в команде!
Мы постоянно растем и развиваемся, поэтому создали отдельную страницу, на которой будут размещены наши актуальные вакансии. Сейчас мы ищем:
👉авторов в наше медиа proglib.io
👉контент-менеджеров для ведения телеграм-каналов
Подробности тут
Мы предлагаем частичную занятость и полностью удаленный формат работы — можно совмещать с основной и находиться в любом месте🌴
Ждем ваших откликов 👾
Мы постоянно растем и развиваемся, поэтому создали отдельную страницу, на которой будут размещены наши актуальные вакансии. Сейчас мы ищем:
👉авторов в наше медиа proglib.io
👉контент-менеджеров для ведения телеграм-каналов
Подробности тут
Мы предлагаем частичную занятость и полностью удаленный формат работы — можно совмещать с основной и находиться в любом месте🌴
Ждем ваших откликов 👾
ad.proglib.io
Вакансии в медиа «Библиотека программиста»
Количество проектов в редакции постоянно растет, так что нам всегда нужны специалисты
Что происходит, когда вы запускаете
go test
? Конечно, Go запускает ваши тесты. Но на практике это далеко не так просто и прямолинейно. Автор статьи Matt T. Proud любит понимать, как работают инструменты, с которыми он работает, поэтому он углубился во внутренности
go test
и обнаружил механизм, который является «довольно элегантным».👉 Читать
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Forwarded from Библиотека программиста | программирование, кодинг, разработка
🐘🧠 Оптимизация использования памяти в PostgreSQL: секреты профессионалов
Сложные (и многочисленные) операции в базе данных требуют солидного объема оперативной памяти — например, для создания набора результатов PostgreSQL обычно приходится:
🔹 Выполнить поиск по индексу.
🔹 Извлечь связанные строки из одной или нескольких таблиц.
🔹 Объединить, отфильтровать, агрегировать и отсортировать кортежи в пригодный для использования результат.
Каждый из этих шагов требует памяти, и PostgreSQL может обрабатывать тысячи таких запросов одновременно. Так что рано или поздно перед разработчиками любого серьезного проекта встает необходимость решения нескольких сложных вопросов:
🔹 Как грамотно оптимизировать использование доступной памяти?
🔹 В каком соотношении распределить ОЗУ между несколькими типами памяти, которые необходимы PostgreSQL для эффективной работы?
🔹 Как предотвратить защитное завершение операционной системой процесса PostgreSQL, который использует слишком много памяти?
Для ответов на все эти вопросы нужно определить, сколько именно памяти использует PostgreSQL для основных процессов — а это сама по себе нетривиальная задача. Советы по настройке памяти так многочисленны и разнообразны, что в них сложно сориентироваться.
Поэтому в этой статье мы сведем всю мудрость экспертов к конкретным шагам, которые помогут максимально эффективно распорядиться доступной памятью.
🔗 Читать статью
🔗 Зеркало
Сложные (и многочисленные) операции в базе данных требуют солидного объема оперативной памяти — например, для создания набора результатов PostgreSQL обычно приходится:
🔹 Выполнить поиск по индексу.
🔹 Извлечь связанные строки из одной или нескольких таблиц.
🔹 Объединить, отфильтровать, агрегировать и отсортировать кортежи в пригодный для использования результат.
Каждый из этих шагов требует памяти, и PostgreSQL может обрабатывать тысячи таких запросов одновременно. Так что рано или поздно перед разработчиками любого серьезного проекта встает необходимость решения нескольких сложных вопросов:
🔹 Как грамотно оптимизировать использование доступной памяти?
🔹 В каком соотношении распределить ОЗУ между несколькими типами памяти, которые необходимы PostgreSQL для эффективной работы?
🔹 Как предотвратить защитное завершение операционной системой процесса PostgreSQL, который использует слишком много памяти?
Для ответов на все эти вопросы нужно определить, сколько именно памяти использует PostgreSQL для основных процессов — а это сама по себе нетривиальная задача. Советы по настройке памяти так многочисленны и разнообразны, что в них сложно сориентироваться.
Поэтому в этой статье мы сведем всю мудрость экспертов к конкретным шагам, которые помогут максимально эффективно распорядиться доступной памятью.
🔗 Читать статью
🔗 Зеркало
👍5❤2
Солидный список с некоторыми выполнимыми и не очень выполнимыми пунктами. С выполнимой стороны есть ordered maps и default arguments. С не очень выполнимой стороны null/nilability — давняя спорная тема, которая, вероятно, нарушит обратную совместимость.
👉 Читать
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱8👍3🤔3
Привет, друзья! 👋
Мы готовим статью на тему: «5 признаков зависимости от программирования». Нам очень важно ваше мнение! Поделитесь своим опытом и советами, и самые интересные из них мы включим в статью.
⌛ Как вы понимаете, что программирование начинает занимать слишком много места в вашей жизни? Какие признаки вы замечаете?
🏄 Какие методы и стратегии вы используете, чтобы сохранить баланс между работой и личной жизнью?
😔 Был ли у вас опыт, когда программирование негативно влияло на ваши отношения с близкими или здоровье? Как вы справились с этим?
Ваши ответы помогут многим! Спасибо за участие!
Мы готовим статью на тему: «5 признаков зависимости от программирования». Нам очень важно ваше мнение! Поделитесь своим опытом и советами, и самые интересные из них мы включим в статью.
⌛ Как вы понимаете, что программирование начинает занимать слишком много места в вашей жизни? Какие признаки вы замечаете?
🏄 Какие методы и стратегии вы используете, чтобы сохранить баланс между работой и личной жизнью?
😔 Был ли у вас опыт, когда программирование негативно влияло на ваши отношения с близкими или здоровье? Как вы справились с этим?
Ваши ответы помогут многим! Спасибо за участие!
🥱8👍4🔥2
Forwarded from Библиотека программиста | программирование, кодинг, разработка
📶 Паттерны коммуникации в распределенных системах
Распределенные системы состоят из многих отдельных частей/узлов, работающих вместе, но физически расположенных в разных местах. Эти части системы должны общаться друг с другом через сеть, чтобы система могла функционировать как единое целое.
Хотя коммуникация критически важна, правильно ее организовать бывает непросто: разработчики иногда пытаются использовать один и тот же подход ко всем задачам коммуникации, что может быть неэффективно. Важно понимать, что существуют разные способы организации коммуникации, и выбор правильного метода зависит от конкретной задачи. Рассмотрим основные паттерны коммуникации, которые можно использовать для решения разных задач.
☑️ Запрос-ответ с HTTP
Этот синхронный паттерн коммуникации предполагает, что один сервис отправляет запрос другому сервису и ожидает ответа или ошибки, блокируя свою работу до получения результата. REST, наиболее популярный архитектурный стиль для этой модели коммуникации, использует методы протокола HTTP — GET, POST, PUT и DELETE.
Однако использование этого паттерна может привести к проблемам, если сервисы образуют цепочку взаимодействий: в таком случае сбой одного из сервисов может привести к отказу всей операции, а также к расточительному использованию ресурсов и каскадным сбоям.
☑️ Общие данные
Этот паттерн часто остается незамеченным, поскольку разработчики не всегда воспринимают его как модель коммуникации. В рамках этого подхода один компонент записывает данные в определенное место, а другой компонент считывает и обрабатывает эти данные. Например, один сервис может загрузить файл в облачное объектное хранилище (например, в корзину Amazon S3), а другой сервис затем извлекает этот файл для дальнейших действий.
Главное преимущество этого паттерна — простота реализации и возможность обеспечения взаимодействия между устаревшими и современными системами без проблем совместимости. Однако он не подходит для сценариев, требующих низкой задержки.
☑️ Асинхронный запрос-ответ
В отличие от синхронного подхода, запрос-ответ может быть реализован асинхронно и без блокировки. В этом случае получающий сервис должен явно знать место назначения для отправки ответа. Для реализации этого паттерна идеально подходят очереди сообщений, которые позволяют буферизовать несколько запросов.
Основная сложность здесь — корреляция между запросом и ответом: экземпляр сервиса, отправивший запрос, может отличаться от экземпляра, получающего ответ, поэтому требуется способ отслеживания запросов.
☑️ Коммуникация на основе событий
В этом подходе сервисы не общаются напрямую друг с другом, а генерируют события, которые могут быть использованы другими сервисами. Это требует наличия места для отправки данных о событиях и механизма, позволяющего получающим сервисам обнаруживать эти события. Брокеры сообщений, такие как RabbitMQ, могут обрабатывать оба этих аспекта. Издатели используют API для отправки событий в брокер, который управляет подписками и уведомляет подписчиков при поступлении события.
Этот паттерн идеально подходит для создания слабосвязанных взаимодействий между сервисами. Однако брокер сообщений должен обеспечивать надежную доставку событий, их упорядочивание и согласованность. Кроме того, добавляется дополнительный компонент в систему.
👨💻 Подробнее читайте в статье.
📨 Материал взят из нашей еженедельной email-рассылки, посвященной бэкенду. Подпишитесь, чтобы быть в числе первых, кто получит дайджест.
Распределенные системы состоят из многих отдельных частей/узлов, работающих вместе, но физически расположенных в разных местах. Эти части системы должны общаться друг с другом через сеть, чтобы система могла функционировать как единое целое.
Хотя коммуникация критически важна, правильно ее организовать бывает непросто: разработчики иногда пытаются использовать один и тот же подход ко всем задачам коммуникации, что может быть неэффективно. Важно понимать, что существуют разные способы организации коммуникации, и выбор правильного метода зависит от конкретной задачи. Рассмотрим основные паттерны коммуникации, которые можно использовать для решения разных задач.
☑️ Запрос-ответ с HTTP
Этот синхронный паттерн коммуникации предполагает, что один сервис отправляет запрос другому сервису и ожидает ответа или ошибки, блокируя свою работу до получения результата. REST, наиболее популярный архитектурный стиль для этой модели коммуникации, использует методы протокола HTTP — GET, POST, PUT и DELETE.
Однако использование этого паттерна может привести к проблемам, если сервисы образуют цепочку взаимодействий: в таком случае сбой одного из сервисов может привести к отказу всей операции, а также к расточительному использованию ресурсов и каскадным сбоям.
☑️ Общие данные
Этот паттерн часто остается незамеченным, поскольку разработчики не всегда воспринимают его как модель коммуникации. В рамках этого подхода один компонент записывает данные в определенное место, а другой компонент считывает и обрабатывает эти данные. Например, один сервис может загрузить файл в облачное объектное хранилище (например, в корзину Amazon S3), а другой сервис затем извлекает этот файл для дальнейших действий.
Главное преимущество этого паттерна — простота реализации и возможность обеспечения взаимодействия между устаревшими и современными системами без проблем совместимости. Однако он не подходит для сценариев, требующих низкой задержки.
☑️ Асинхронный запрос-ответ
В отличие от синхронного подхода, запрос-ответ может быть реализован асинхронно и без блокировки. В этом случае получающий сервис должен явно знать место назначения для отправки ответа. Для реализации этого паттерна идеально подходят очереди сообщений, которые позволяют буферизовать несколько запросов.
Основная сложность здесь — корреляция между запросом и ответом: экземпляр сервиса, отправивший запрос, может отличаться от экземпляра, получающего ответ, поэтому требуется способ отслеживания запросов.
☑️ Коммуникация на основе событий
В этом подходе сервисы не общаются напрямую друг с другом, а генерируют события, которые могут быть использованы другими сервисами. Это требует наличия места для отправки данных о событиях и механизма, позволяющего получающим сервисам обнаруживать эти события. Брокеры сообщений, такие как RabbitMQ, могут обрабатывать оба этих аспекта. Издатели используют API для отправки событий в брокер, который управляет подписками и уведомляет подписчиков при поступлении события.
Этот паттерн идеально подходит для создания слабосвязанных взаимодействий между сервисами. Однако брокер сообщений должен обеспечивать надежную доставку событий, их упорядочивание и согласованность. Кроме того, добавляется дополнительный компонент в систему.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤2🔥2🥱1
Текстовая версия выступления Ian Lance Taylor на GopherCon 2024 о том, почему эта фича была добавлена, что из себя представляет и как ее использовать.
👉 Читать
Please open Telegram to view this post
VIEW IN TELEGRAM
go.dev
Range Over Function Types - The Go Programming Language
A description of range over function types, a new feature in Go 1.23.
👍13🥱1
Очередной гайд от Phuong Le о работе
go mod vendor
под капотом.👉 Читать
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🥱3
Привет, друзья! 👋
Мы готовим статью о прокрастинации среди разработчиков и хотим узнать ваше мнение! 🤓 Поделитесь своим опытом, а самые интересные и полезные советы мы обязательно включим в нашу статью.
❓ Какая самая необычная причина прокрастинации у вас была в работе над проектом?
❓ Какой метод борьбы с прокрастинацией оказался для вас наиболее эффективным?
❓ Как вы справляетесь с когнитивной перегрузкой во время работы над сложными задачами?
Не стесняйтесь делиться своими историями и лайфхаками в комментариях! 💬 Ваш опыт может помочь другим разработчикам справиться с прокрастинацией. Спасибо за участие!
Мы готовим статью о прокрастинации среди разработчиков и хотим узнать ваше мнение! 🤓 Поделитесь своим опытом, а самые интересные и полезные советы мы обязательно включим в нашу статью.
❓ Какая самая необычная причина прокрастинации у вас была в работе над проектом?
❓ Какой метод борьбы с прокрастинацией оказался для вас наиболее эффективным?
❓ Как вы справляетесь с когнитивной перегрузкой во время работы над сложными задачами?
Не стесняйтесь делиться своими историями и лайфхаками в комментариях! 💬 Ваш опыт может помочь другим разработчикам справиться с прокрастинацией. Спасибо за участие!
👍8
Что первым приходит в голову разработчика, когда слышишь про Go? Google и микросервисы? Автор тоже так думал, но реальность оказалась значительно интереснее.
Под катом — разработка Desktop-приложения с учетом реалий Windows, которое запустит встроенный веб-сервер, с методом REST API на ассемблере.
👉 Читать
Под катом — разработка Desktop-приложения с учетом реалий Windows, которое запустит встроенный веб-сервер, с методом REST API на ассемблере.
👉 Читать
👍20🥱8
🏃 Самоучитель по Go для начинающих. Часть 15. Конкурентность. Горутины. Каналы
В 15-й части самоучителя мы разберем работу базовых сущностей ОС для погружения в парадигму конкурентного программирования, а затем изучим основные способы её реализации в Go с помощью горутин и каналов.
👉 Читать гайд
📌 Остальные части в серии:
1. Особенности и сфера применения Go, установка, настройка
2. Ресурсы для изучения Go с нуля
3. Организация кода. Пакеты, импорты, модули. Ввод-вывод текста.
4. Переменные. Типы данных и их преобразования. Основные операторы
5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы
6. Функции и аргументы. Области видимости. Рекурсия. Defer
7. Массивы и слайсы. Append и сopy. Пакет slices
8. Строки, руны, байты. Пакет strings. Хеш-таблица (map)
9. Структуры и методы. Интерфейсы. Указатели. Основы ООП
10. Введение в ООП. Наследование, абстракция, полиморфизм, инкапсуляция
11. Обработка ошибок. Паника. Восстановление. Логирование
12. Обобщенное программирование. Дженерики
13. Работа с датой и временем. Пакет time
14. Интерфейсы ввода-вывода. Буферизация. Работа с файлами. Пакеты io, bufio, os
В 15-й части самоучителя мы разберем работу базовых сущностей ОС для погружения в парадигму конкурентного программирования, а затем изучим основные способы её реализации в Go с помощью горутин и каналов.
👉 Читать гайд
📌 Остальные части в серии:
1. Особенности и сфера применения Go, установка, настройка
2. Ресурсы для изучения Go с нуля
3. Организация кода. Пакеты, импорты, модули. Ввод-вывод текста.
4. Переменные. Типы данных и их преобразования. Основные операторы
5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы
6. Функции и аргументы. Области видимости. Рекурсия. Defer
7. Массивы и слайсы. Append и сopy. Пакет slices
8. Строки, руны, байты. Пакет strings. Хеш-таблица (map)
9. Структуры и методы. Интерфейсы. Указатели. Основы ООП
10. Введение в ООП. Наследование, абстракция, полиморфизм, инкапсуляция
11. Обработка ошибок. Паника. Восстановление. Логирование
12. Обобщенное программирование. Дженерики
13. Работа с датой и временем. Пакет time
14. Интерфейсы ввода-вывода. Буферизация. Работа с файлами. Пакеты io, bufio, os
👍16🔥2
Как этот стиль может улучшить читаемость/поддержку кода в проектах на Go и какие потенциальные подводные камни/ограничения можно встретить? Обо всем этом — под катом.
Вы узнаете, как с помощью CPS сделать инверсию control flow, как скрывать системные детали реализации и безопасно управлять ресурсами, таким образом получить надежный и читаемый код.
🔗 Читать
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Применения Continuation-passing style в Go
В этой статье мы рассмотрим концепцию программирования в стиле передачи продолжений и примеры его применения, исследуем, как этот стиль может улучшить читаемость и поддержку кода в приложениях на Go....
🥱13👍6🔥4😢4❤1