Пакет context в Go: взгляд профессионала
Пакет context появился как x/net/context в 2014 году и быстро обрел популярность. В 2016 году его добавили в стандартную библиотеку Go 1.7. С тех пор практически ни одно приложение на Go не обходится без его использования, потому что пакет ощутимо упрощает многие задачи.
💎 Чат: ссылка
🌍 Статья: https://habr.com/ru/companies/pt/articles/764850/
Пакет context появился как x/net/context в 2014 году и быстро обрел популярность. В 2016 году его добавили в стандартную библиотеку Go 1.7. С тех пор практически ни одно приложение на Go не обходится без его использования, потому что пакет ощутимо упрощает многие задачи.
💎 Чат: ссылка
🌍 Статья: https://habr.com/ru/companies/pt/articles/764850/
🧰 Как устроены мапы под капотом: гайд для Go-разработчика
Павел Комаров из AvitoTech в подробностях рассмотрел процесс записи и чтения данных в мапы, важность передачи количества элементов при создании мапы, а также уделил внимание проблеме переполнения и эвакуации элементов, даже до уровня отдельных битов.
👉 Читать
Павел Комаров из AvitoTech в подробностях рассмотрел процесс записи и чтения данных в мапы, важность передачи количества элементов при создании мапы, а также уделил внимание проблеме переполнения и эвакуации элементов, даже до уровня отдельных битов.
👉 Читать
🤔 Context vs структура: следует ли передавать информацию, специфичную для запроса, через
HTTP-обработчики могут использовать контекст для управления тайм-аутами запросов или отменой в рамках запроса. Тип
❓Следует ли использовать этот механизм для передачи информации по цепочке вызовов запроса? Или лучше использовать обычную структуру?
Вот две причины, по которым использование
Значения в
Если вы видите функцию, принимающую параметр
❓Но разве
Чистый код сам по себе не является целью. Код не чист только потому, что он короткий. Код чистый, если читатель может ясно видеть, что он делает.
❓Так
Значения в контексте могут быть полезны, если они не критичны для бизнес-логики приложения. Например, совершенно нормально передавать идентификаторы запросов для логирования или измерения метрик. Читатель все равно сможет понять логику кода, и если что-то пойдет не так с этим идентификатором, это повлияет только на логирование или метрики приложения, но не на результат запроса.
💡Если данные важны для вашей бизнес-логики, не помещайте их в
#tip
context.Context
?HTTP-обработчики могут использовать контекст для управления тайм-аутами запросов или отменой в рамках запроса. Тип
Context
также позволяет передавать значения (например, идентификатор пользователя, связанный с запросом) другим функциям.❓Следует ли использовать этот механизм для передачи информации по цепочке вызовов запроса? Или лучше использовать обычную структуру?
Вот две причины, по которым использование
Context
для передачи значений может быть плохой идеей:Значения в
Context
представляют собой пары ключ/значение, где ключ и значение являются пустыми интерфейсами (т. е. any
). Другими словами, значения в контексте — это как мешок со всем подряд. Компилятор не может помочь вам отловить ошибки типов или даже проверить, есть ли информация. Удачи в устранении неполадок 😉Если вы видите функцию, принимающую параметр
Context
, вы не можете сказать, что внутри. Если вы видите функцию, которая принимает параметр структуры, вы можете ясно видеть, что данные передаются, и что это за данные.❓Но разве
doSomething(ctx)
не выглядит намного чище, чем doSomething(ctx, someStruct)
?Чистый код сам по себе не является целью. Код не чист только потому, что он короткий. Код чистый, если читатель может ясно видеть, что он делает.
❓Так
context.WithValue()
следует избегать?Значения в контексте могут быть полезны, если они не критичны для бизнес-логики приложения. Например, совершенно нормально передавать идентификаторы запросов для логирования или измерения метрик. Читатель все равно сможет понять логику кода, и если что-то пойдет не так с этим идентификатором, это повлияет только на логирование или метрики приложения, но не на результат запроса.
💡Если данные важны для вашей бизнес-логики, не помещайте их в
Context
.#tip
Ответ на «Как проверить тип переменной в среде выполнения?»
Лучшим способом проверки типа переменной при выполнении является Type Switch (переключатель типов). Переключатель типов оценивает переменные по типу, а не значению. Каждый такой переключатель содержит не менее одного
Например, можно создать Type Switch, проверяющий, содержит ли значение i интерфейса тип
Лучшим способом проверки типа переменной при выполнении является Type Switch (переключатель типов). Переключатель типов оценивает переменные по типу, а не значению. Каждый такой переключатель содержит не менее одного
case
, который выступает в роли инструкции условия, а также кейс default
, которые выполняется, если ни один из кейсов не верен.Например, можно создать Type Switch, проверяющий, содержит ли значение i интерфейса тип
int
или string
:package main#собеседование
import "fmt"
func do(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("Double %v is %v\n", v, v*2)
case string:
fmt.Printf("%q is %v bytes long\n", v, len(v))
default:
fmt.Printf("I don't know type %T!\n", v)
}
}
func main() {
do(21)
do("hello")
do(true)
}
💡Стек или куча?
🤔 Живет ли переменная на стеке вызовов, или она динамически выделена в куче?
В большинстве случаев вам не стоит беспокоиться об этом. Go собирает мусор и автоматически очищает неиспользуемые переменные.
Однако сборка мусора имеет свою цену, поэтому чем меньше выделений делает ваш код, тем быстрее он может работать.
📌 Как узнать, выделяется ли переменная в куче?
Некоторые операции по умолчанию вызывают выделение памяти в куче и поэтому легко обнаруживаются и исправляются. Вот несколько примеров:
🔸Строковые переменные неизменяемы. Конкатенация двух строк приводит к новой аллокации и сборке мусора. В качестве альтернативы можно использовать
🔸Срезы, которые растут за пределы своей емкости, реаллоцируются. Решение: предварительно выделить срез с помощью
🔸Когда функция создает локальную переменную и возвращает указатель на эту переменную, переменная должна быть выделена в куче.
📌 Однако есть ситуации, когда выделения в куче неочевидны. Подумайте об указателях, скрытых внутри других типов данных, таких как срезы или мапы. Или рассмотрите массивы. Если массив слишком большой, чтобы жить на стеке, он выделяется в куче.
📌 Как найти эти случаи выделения в куче?
Запустите или скомпилируйте свой код с флагом сборки мусора "
#tip
🤔 Живет ли переменная на стеке вызовов, или она динамически выделена в куче?
В большинстве случаев вам не стоит беспокоиться об этом. Go собирает мусор и автоматически очищает неиспользуемые переменные.
Однако сборка мусора имеет свою цену, поэтому чем меньше выделений делает ваш код, тем быстрее он может работать.
📌 Как узнать, выделяется ли переменная в куче?
Некоторые операции по умолчанию вызывают выделение памяти в куче и поэтому легко обнаруживаются и исправляются. Вот несколько примеров:
🔸Строковые переменные неизменяемы. Конкатенация двух строк приводит к новой аллокации и сборке мусора. В качестве альтернативы можно использовать
strings.Builde
r.🔸Срезы, которые растут за пределы своей емкости, реаллоцируются. Решение: предварительно выделить срез с помощью
make()
.🔸Когда функция создает локальную переменную и возвращает указатель на эту переменную, переменная должна быть выделена в куче.
📌 Однако есть ситуации, когда выделения в куче неочевидны. Подумайте об указателях, скрытых внутри других типов данных, таких как срезы или мапы. Или рассмотрите массивы. Если массив слишком большой, чтобы жить на стеке, он выделяется в куче.
📌 Как найти эти случаи выделения в куче?
Запустите или скомпилируйте свой код с флагом сборки мусора "
-
m", и команда Go выведет заметку каждый раз, когда переменная перемещается или уходит со стека в кучу:go run -gcflags "-m"
или
go tools compile -m
#tip
🔥 Пройди подробный ТУР по Golang с примерами (английский язык)
Это материал для разработчиков среднего уровня, имеющих некоторый опыт работы с другими языками программирования и желающих изучить язык Go. Мы считаем, что этот материал идеально подходит для тех, кто хочет начать изучение Go или получить более глубокое представление о языке и его внутреннем устройстве.
💎 Чат: ссылка
Подробнее: https://tour.ardanlabs.com/tour/list
Это материал для разработчиков среднего уровня, имеющих некоторый опыт работы с другими языками программирования и желающих изучить язык Go. Мы считаем, что этот материал идеально подходит для тех, кто хочет начать изучение Go или получить более глубокое представление о языке и его внутреннем устройстве.
💎 Чат: ссылка
Подробнее: https://tour.ardanlabs.com/tour/list
⚙️Три паттерна конкурентного кода: гайд для Go-разработчика
Часто для погружения в ту или иную тему необходима мотивация — например, можно в проекте увидеть странное поведение кода, которое вызывает больше вопросов, чем ответов.
Именно так получилось у автора статьи. Он встретил логику ограничения потоков выполнения, основанную на результате выполнения функции
Это подходит под паттерн с параллельными вычислениями на одном процессоре, но использовалось для ограничения количества одновременных запросов к удаленному серверу.
👉 Читать
Часто для погружения в ту или иную тему необходима мотивация — например, можно в проекте увидеть странное поведение кода, которое вызывает больше вопросов, чем ответов.
Именно так получилось у автора статьи. Он встретил логику ограничения потоков выполнения, основанную на результате выполнения функции
GOMAXPROCS(0)
, которая по умолчанию будет равна runtime.NumCPU
. Это подходит под паттерн с параллельными вычислениями на одном процессоре, но использовалось для ограничения количества одновременных запросов к удаленному серверу.
👉 Читать
Нарезаем массивы правильно в Go
💎 Чат: ссылка
Второй очерк из цикла приключений в мире сусликов.
Это вторая статья серии небольших рассказов о необычных подводных камнях, которые можно встретить в начале разработки на Go. Напоминаю, что в статьях есть примеры кода, будьте с ними аккуратнее - не все из них будут компилироваться и работать, читайте внимательно комментарии, везде указано, на какой строке происходит ошибка. Также в блоках кода везде табуляция заменена на пробелы - это сделано намеренно, чтобы статьи выглядели у всех одинаково.
Подробнее: https://habr.com/ru/post/597521/
💎 Чат: ссылка
Второй очерк из цикла приключений в мире сусликов.
Это вторая статья серии небольших рассказов о необычных подводных камнях, которые можно встретить в начале разработки на Go. Напоминаю, что в статьях есть примеры кода, будьте с ними аккуратнее - не все из них будут компилироваться и работать, читайте внимательно комментарии, везде указано, на какой строке происходит ошибка. Также в блоках кода везде табуляция заменена на пробелы - это сделано намеренно, чтобы статьи выглядели у всех одинаково.
Подробнее: https://habr.com/ru/post/597521/
📕 System Design Blueprint: The Ultimate Guide.
Шаблон-шпаргалка для решения различных проблем системного дизайна на собеседованиях.
В нем кратко затронуты следующие вопросы:
- Балансировка нагрузки
- API
- Коммуникационные протоколы
- CDN
- База данных
- Кэш
- Очередь сообщений
- Генерация уникальных идентификаторов
- Масштабируемость
- Доступность
- Производительность
- Безопасность
- Отказоустойчивость
- И многое другое
@golangprofi
Шаблон-шпаргалка для решения различных проблем системного дизайна на собеседованиях.
В нем кратко затронуты следующие вопросы:
- Балансировка нагрузки
- API
- Коммуникационные протоколы
- CDN
- База данных
- Кэш
- Очередь сообщений
- Генерация уникальных идентификаторов
- Масштабируемость
- Доступность
- Производительность
- Безопасность
- Отказоустойчивость
- И многое другое
@golangprofi
🎮 Dendy - это эмулятор NES/Famicom, написанный на Go и названный в честь советского клона Famicom, который был у многих в детстве.
▪️ Github
@golangprofi
$ go install github.com/maxpoletaev/dendy/cmd/dendy@latest
▪️ Github
@golangprofi