🎉 Релиз Go 1.21.1 и 1.20.8
🔐 Новые релизы включают исправления безопасности для cmd/go (CVE-2023-39320), html/template (CVE-2023-39318, CVE-2023-39319) и crypto/tls.
🗣 Announcement: https://groups.google.com/g/golang-announce/c/Fm51GRLNRvM
⬇️ Загрузить: https://go.dev/dl/#go1.21.1
@golang_interview
🔐 Новые релизы включают исправления безопасности для cmd/go (CVE-2023-39320), html/template (CVE-2023-39318, CVE-2023-39319) и crypto/tls.
🗣 Announcement: https://groups.google.com/g/golang-announce/c/Fm51GRLNRvM
⬇️ Загрузить: https://go.dev/dl/#go1.21.1
@golang_interview
В Go-программе для сбора и экспорта метрик в Prometheus обычно используется пакет github.com/prometheus/client_golang/prometheus. Этот пакет предоставляет стандартный набор метрик и инструментов для работы с Prometheus.
Вот несколько основных типов метрик, которые можно использовать с помощью пакета prometheus:
Counter: Счетчики (Counter) представляют собой метрики, которые увеличиваются только вверх и никогда не уменьшаются. Они полезны для подсчета количества событий или запросов. Пример:
counter := prometheus.NewCounter(prometheus.CounterOpts{
Name: "my_counter",
Help: "This is my counter",
})
counter.Inc()
Gauge: Градусники (Gauge) представляют собой метрики, которые могут изменяться вверх и вниз. Они полезны для отслеживания изменяющихся значений, таких как количество активных соединений или текущая нагрузка на систему. Пример:
gauge := prometheus.NewGauge(prometheus.GaugeOpts{
Name: "my_gauge",
Help: "This is my gauge",
})
gauge.Set(42)
Histogram: Гистограммы (Histogram) представляют собой метрики, которые измеряют распределение значений в заданном диапазоне. Они полезны для измерения времени выполнения операций или размера запросов. Пример:
histogram := prometheus.NewHistogram(prometheus.HistogramOpts{
Name: "my_histogram",
Help: "This is my histogram",
Buckets: []float64{0.1, 0.5, 1, 2, 5},
})
histogram.Observe(0.6)
Summary: Суммары (Summary) также представляют собой метрики, которые измеряют распределение значений, но с учетом квантилей. Они полезны для измерения производительности и времени выполнения операций. Пример:
summary := prometheus.NewSummary(prometheus.SummaryOpts{
Name: "my_summary",
Help: "This is my summary",
})
summary.Observe(2.5)
Кроме того, пакет github.com/prometheus/client_golang/prometheus также предоставляет дополнительные инструменты для регистрации метрик (Register), создания коллекторов (Collector), экспорта метрик (HTTPHandler) и т.д.
Это лишь небольшой обзор стандартного набора метрик, доступных в Go-программе через пакет prometheus. Более подробную информацию о создании и использовании метрик в Prometheus вы можете найти в официальной документации Prometheus для Go-программы: https://pkg.go.dev/github.com/prometheus/client_golang/prometheus
Там вы найдете более подробную информацию о различных типах метрик, настройке и регистрации метрик, использовании коллекторов, экспорте метрик через HTTP и многое другое.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
📌 Предположим, ваша функция должна возвращать детализированные Recoverable и Fatal ошибки. Как это реализовано в пакете net? Как это надо делать в современном Go
В пакете net в стандартной библиотеке Go возвращение детализированных ошибок реализовано с помощью ошибок, которые являются значениями пользовательских типов, реализующих интерфейс net.Error. Этот интерфейс определен следующим образом:
Интерфейс
В современном Go, начиная с версии 1.13, рекомендуется использовать синтаксис ошибок, основанный на типах, с помощью применения пакета errors и интерфейса
Вот пример, как можно реализовать детализированные ошибки в современном Go:
В этом примере у нас есть два типа ошибок:
Функция
Важно отметить, что настройка и использование детализированных ошибок может различаться в зависимости от конкретной задачи и предпочтений разработчика. Рекомендуется следовать общим рекомендациям и принципам языка Go при работе с обработкой ошибок. Например, рекомендуется использовать типы ошибок, которые являются значениями пользовательских типов и реализуют интерфейс error, чтобы их можно было легко сравнивать с помощью функции
Всегда стоит помнить, что обработка ошибок - важная часть разработки программного обеспечения, и хорошая практика заключается в предоставлении четкой информации о возникших ошибках, чтобы помочь пользователям программы или другим разработчикам понять, что пошло не так и как это исправить.
@golang_interview
В пакете net в стандартной библиотеке Go возвращение детализированных ошибок реализовано с помощью ошибок, которые являются значениями пользовательских типов, реализующих интерфейс net.Error. Этот интерфейс определен следующим образом:
type Error interface {
error
Timeout() bool // возвращает true, если ошибка связана с таймаутом
Temporary() bool // возвращает true, если ошибка является временной
}
Интерфейс
net.Error
включает методы Timeout() и Temporary(), которые позволяют клиентам проверять, является ли ошибка связанной с таймаутом или временной. Это позволяет клиентам принимать соответствующие действия в зависимости от типа ошибки.В современном Go, начиная с версии 1.13, рекомендуется использовать синтаксис ошибок, основанный на типах, с помощью применения пакета errors и интерфейса
fmt.Formatter
. Этот подход позволяет создавать богатые по содержанию и информативные ошибки, которые могут хранить дополнительные данные и форматироваться в нужном формате при выводе.Вот пример, как можно реализовать детализированные ошибки в современном Go:
package main
import (
"errors"
"fmt"
)
type RecoverableError struct {
Message string
}
func (e *RecoverableError) Error() string {
return fmt.Sprintf("RecoverableError: %s", e.Message)
}
type FatalError struct {
Message string
}
func (e *FatalError) Error() string {
return fmt.Sprintf("FatalError: %s", e.Message)
}
func main() {
err := doSomething()
switch {
case errors.Is(err, &RecoverableError{}):
fmt.Println("Recoverable error:", err)
case errors.Is(err, &FatalError{}):
fmt.Println("Fatal error:", err)
default:
fmt.Println("Unknown error:", err)
}
}
func doSomething() error {
// Ваша логика здесь
return &RecoverableError{Message: "Something went wrong"}
}
В этом примере у нас есть два типа ошибок:
RecoverableError
и FatalError. Оба типа реализуют интерфейс error и предоставляют дополнительные данные в своих методах Error(). Функция doSomething() возвращает ошибку типа RecoverableError.Функция
main()
использует функцию errors.Is() для проверки типа ошибки и выполняет соответствующие действия в зависимости от типа ошибки.Важно отметить, что настройка и использование детализированных ошибок может различаться в зависимости от конкретной задачи и предпочтений разработчика. Рекомендуется следовать общим рекомендациям и принципам языка Go при работе с обработкой ошибок. Например, рекомендуется использовать типы ошибок, которые являются значениями пользовательских типов и реализуют интерфейс error, чтобы их можно было легко сравнивать с помощью функции
errors.Is(
), как показано в примере выше. Также рекомендуется предоставлять информативные сообщения об ошибках, чтобы облегчить отладку и понимание причины ошибки.Всегда стоит помнить, что обработка ошибок - важная часть разработки программного обеспечения, и хорошая практика заключается в предоставлении четкой информации о возникших ошибках, чтобы помочь пользователям программы или другим разработчикам понять, что пошло не так и как это исправить.
@golang_interview
В Go вы можете использовать встроенный профайлер для сбора информации о производительности вашего приложения. Для этого вам нужно импортировать пакет net/http/pprof и зарегистрировать его обработчики HTTP.
Вот простой пример того, как встроить стандартный профайлер в свое приложение:
package main
import (
"log"
"net/http"
_ "net/http/pprof"
)
func main() {
// Регистрируем обработчики профайлера
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// Ваше приложение
// ...
}
В этом примере мы импортируем пакет net/http/
pprof и регистрируем его обработчики HTTP с помощью функции http.ListenAndServe(). Обработчики будут доступны по адресу localhost:6060.
После запуска вашего приложения вы можете открыть веб-браузер и перейти по адресу http://localhost:6060/debug/pprof/, чтобы получить доступ к различным профилировочным эндпоинтам. Например:
• http://localhost:6060/debug/pprof/profile - профилирование CPU
• http://localhost:6060/debug/pprof/heap - профилирование памяти
• http://localhost:6060/debug/pprof/block - профилирование блокировок
• http://localhost:6060/debug/pprof/goroutine - профилирование горутин
Вы можете использовать инструменты, такие как go tool pprof, чтобы анализировать собранные профилировочные данные и получать информацию о времени выполнения, утечках памяти, блокировках и других аспектах производительности вашего приложения.
Обратите внимание, что встроенный профайлер должен использоваться только для разработки и отладки, и не рекомендуется использовать его в продакшн-среде, так как он может иметь негативное влияние на производительность вашего приложения.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Стандартная библиотека Go (stdlib) предоставляет два типа мьютексов для синхронизации доступа к общим ресурсам:
sync.Mutex:
Это самый простой тип мьютекса, который предоставляется стандартной библиотекой Go. Он обеспечивает эксклюзивную блокировку (exclusive lock), что означает, что только одна горутина может захватить мьютекс и получить доступ к общему ресурсу. Если другая горутина пытается захватить мьютекс, пока он уже заблокирован, она будет ожидать его освобождения.Пример использования sync.Mutex:
var mutex sync.Mutex
var sharedResource int
// Горутина 1
mutex.Lock()
sharedResource = 42
mutex.Unlock()
// Горутина 2
mutex.Lock()
fmt.Println(sharedResource)
mutex.Unlock()
sync.RWMutex
: Этот тип мьютекса, называемый также мьютексом чтения/записи (read/write mutex), обеспечивает более гибкую блокировку. Он позволяет нескольким горутинам захватывать мьютекс только для чтения (shared lock), разрешая параллельный доступ к общему ресурсу для чтения. Однако, при записи (exclusive lock) мьютекс блокируется, и другие горутины должны ждать его освобождения.Пример использования sync.RWMutex:
var rwMutex sync.RWMutex
var sharedResource int
// Горутина 1 для записи
rwMutex.Lock()
sharedResource = 42
rwMutex.Unlock()
// Горутина 2 для чтения
rwMutex.RLock()
fmt.Println(sharedResource)
rwMutex.RUnlock()
Оба типа мьютексов,
sync.Mutex
и sync.RWMutex, являются потокобезопасными и предоставляют механизмы для синхронизации доступа к общим ресурсам в многопоточной среде. Выбор между ними зависит от требований вашего кода: если вам нужна только эксклюзивная блокировка, используйте sync.Mutex, а если вам требуется поддержка одновременного чтения и блокировки записи, используйте sync.RWMutex.
Пишите свой ответ в комментариях👇
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
В язке Go пофиксили циклы. В прошлых версиях циклы имели проблемы с замыканиями, потому что переменная цикла имела скоуп всего цикла, а не одной итерации, в новых версиях этого не будет.
https://go.dev/blog/loopvar-preview
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
go.dev
Fixing For Loops in Go 1.22 - The Go Programming Language
Go 1.21 shipped a preview of a change in Go 1.22 to make for loops less error-prone.
Порядок перебора элементов в map в Go является неопределенным и не гарантированным. Это связано с тем, что map внутренне реализован как хэш-таблица, и порядок элементов может меняться при каждой итерации по map.
Если вам требуется определенный порядок элементов, вам необходимо явно сортировать ключи или значения перед их использованием. Например, вы можете сначала извлечь ключи из map в срез (
slice
), отсортировать этот срез и затем итерироваться по отсортированным ключам для доступа к значениям.Пример сортировки ключей map перед итерацией:
m := map[string]int{
"banana": 2,
"apple": 1,
"cherry": 3,
}
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
fmt.Println(k, m[k])
}
В этом примере мы создаем map с неупорядоченными ключами и значениями. Затем мы извлекаем ключи из map в срез keys, сортируем этот срез с помощью
sort.Strings
, а затем итерируемся по отсортированным ключам, чтобы получить доступ к соответствующим значениям.Важно отметить, что сортировка выполняется на ключах, а не на значениях map. Если вам нужно сортировать по значениям, вы можете использовать дополнительные структуры данных или преобразовывать map в список пар ключ-значение и сортировать его.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Описание интерфейса следует помещать в пакете, где этот интерфейс используется, а не в пакете с реализацией. Это согласуется с принципом разделения интерфейса и реализации (Interface Segregation Principle) из принципов SOLID.
Согласно этому принципу, клиенты не должны зависеть от интерфейсов, которые они не используют. Помещение описания интерфейса в пакете, где он используется, позволяет клиентам работать с интерфейсом, не имея прямой зависимости от конкретной реализации.
Если описание интерфейса было бы помещено в пакете с реализацией, клиентам, которым нужно использовать этот интерфейс, пришлось бы иметь зависимость от пакета с реализацией. Это нарушает принцип разделения интерфейса и реализации и делает код менее гибким и сложным для поддержки и расширения.
Однако, хорошей практикой является помещение интерфейса и его реализации в одном пакете, если они плотно связаны и используются только внутри этого пакета. Это позволяет легче поддерживать код и обеспечивает более прозрачное использование интерфейса внутри пакета.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Для сортировки массива структур по алфавиту по полю Name в Go, вы можете использовать интерфейс sort.Interface и функцию
sort.Sort()
из пакета sort.Вот пример кода, который демонстрирует, как отсортировать массив структур по полю
Name
:package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
type ByName []Person
func (a ByName) Len() int { return len(a) }
func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByName) Less(i, j int) bool { return a[i].Name < a[j].Name }
func main() {
people := []Person{
{Name: "Alice", Age: 25},
{Name: "Charlie", Age: 30},
{Name: "Bob", Age: 20},
}
sort.Sort(ByName(people))
for _, person := range people {
fmt.Println(person.Name, person.Age)
}
}
В этом примере мы определяем тип Person для представления структуры человека с полями Name
и Age
. Затем мы определяем тип ByName
, который является срезом структур Person
. Мы также реализуем методы Len(), Swap(),
и Less()
для типа ByName,
чтобы он соответствовал интерфейсу sort.Interface.
Затем мы создаем срез структур Person и заполняем его некоторыми значениями. Далее мы вызываем
sort.Sort(ByName(people))
, чтобы отсортировать срез структур по полю Name
. Наконец, мы проходимся по отсортированному срезу и выводим отсортированные значения.В результате выполнения этого кода вы увидите отсортированный по алфавиту список людей по полю
Name
, сопровождающийся их возрастом.@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
В Go можно использовать один и тот же буфер
[]byte
в нескольких горутинах, но это требует дополнительных мер предосторожности для обеспечения безопасности и избежания гонок данных (data races
).Одним из подходов к безопасному использованию одного буфера
[]byte
в нескольких горутинах является синхронизация доступа к нему с помощью мьютексов или других механизмов синхронизации, таких как sync.RWMutex
. Мьютексы позволяют горутинам синхронизировать свой доступ к общему ресурсу и предотвращать одновременную запись или чтение из буфера.Вот пример использования мьютекса для безопасного доступа к общему буферу
[]byte
:var bufferMutex sync.Mutex
var buffer []byte
func writeToBuffer(data []byte) {
bufferMutex.Lock()
defer bufferMutex.Unlock()
// Здесь происходит запись в буфер
// ...
}
func readFromBuffer() []byte {
bufferMutex.Lock()
defer bufferMutex.Unlock()
// Здесь происходит чтение из буфера
// ...
return buffer
}
В этом примере мьютекс
bufferMutex
используется для блокировки доступа к буферу []byte
перед его записью или чтением. Это гарантирует, что только одна горутина имеет доступ к буферу в определенный момент времени.Однако, важно помнить, что использование общего буфера []byte может быть проблематичным, особенно если горутины модифицируют его содержимое. Если горутины выполняют параллельные записи в буфер, могут возникнуть состояния гонки и непредсказуемые результаты. В таких случаях рекомендуется использовать другие механизмы синхронизации, такие как каналы (channels) или пулы буферов, чтобы гарантировать безопасность и предсказуемость работы с данными в многопоточной среде.
В целом, использование одного и того же буфера
[]byte
в нескольких горутинах возможно, но требует осторожности и правильной синхронизации доступа к нему для обеспечения безопасности данных.@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Поиск проблем производительности на продукционной среде может быть сложным и требует систематического подхода. Вот несколько способов, которые могут помочь вам найти проблемы производительности на проде:
Мониторинг ресурсов: Используйте инструменты мониторинга, такие как системные метрики, мониторинг нагрузки
CPU
, памяти, диска и сети. Это поможет вам определить, какие ресурсы используются в большей степени и могут быть узкими местами.Профилирование кода: Используйте профилирование кода для идентификации узких мест в вашем коде. В
Go
вы можете использовать инструменты профилирования, такие как pprof и go tool pprof, чтобы получить информацию о времени выполнения и использовании памяти в вашей программе.Логирование: Разместите подробные и информативные логи в вашем приложении. Логирование может помочь идентифицировать узкие места в вашем коде или обнаружить неожиданные события или проблемы использования ресурсов.
Измерение времени выполнения: Измерьте время выполнения различных частей вашего кода, чтобы определить, какие операции занимают больше всего времени. В Go вы можете использовать пакет time для измерения времени выполнения конкретных операций.
Анализ запросов и данных: Используйте инструменты для анализа запросов и данных, чтобы найти более долгие или медленные запросы, определить проблемы с производительностью базы данных или идентифицировать неэффективные запросы.
Масштабирование и горизонтальное масштабирование: Если ваше приложение испытывает проблемы с производительностью на проде, рассмотрите возможность масштабирования, как вертикального (увеличение ресурсов на одном сервере) и горизонтального (добавление дополнительных серверов). Это может помочь распределить нагрузку и повысить производительность.
Анализ кода и оптимизация: Просмотрите свой код и ищите возможности для оптимизации. Иногда простые изменения в алгоритмах или структурах данных могут привести к значительному улучшению производительности.
Важно помнить, что поиск проблем производительности является итеративным процессом, и требует тщательного анализа и экспериментов. При обнаружении проблемы, попробуйте реализовать оптимизации и изменения, затем проведите тестирование и измерения производительности, чтобы убедиться, что внесенные изменения действительно улучшают производительность.
Также стоит помнить, что проблемы производительности могут быть вызваны различными факторами, включая неэффективный код, проблемы с инфраструктурой, сетью или базой данных. Поэтому важно анализировать не только код приложения, но и внутренние и внешние факторы, которые могут влиять на производительность.
Наконец, не забывайте о регулярном мониторинге и тестировании производительности вашего приложения на проде. Это поможет вам отслеживать изменения производительности с течением времени и реагировать на проблемы, которые могут возникнуть.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
package main
import "fmt"
type Node struct {
Val int
Next *Node
}
func reverseLinkedList(head *Node) *Node {
var prev *Node
curr := head
for curr != nil {
Next := curr.Next
curr.Next = prev
prev = curr
curr = Next
}
return prev
}
// можно сократить curr
// func reverseLinkedList(head *Node) *Node {
// var prev *Node
// for head != nil {
// Next := head.Next
// head.Next = prev
// prev = head
// head = Next
// }
// return prev
// }
// можно сократить Next (через множественное присваивание)
// func reverseLinkedList(head *Node) *Node {
// var prev *Node
// for head != nil {
// head.Next, prev, head = prev, head, head.Next
// }
// return prev
// }
// или создавая новые узлы
// func reverseLinkedList(head *Node) *Node {
// var result *Node
// curr := head
// for curr != nil {
// result = &Node{curr.Val, result}
// curr = curr.Next
// }
// return result
// }
func printLinkedList(head *Node) {
current := head
for current != nil {
fmt.Printf("%d -> ", current.Val)
current = current.Next
}
fmt.Println("nil")
}
func main() {
node1 := &Node{Val: 1}
node2 := &Node{Val: 2}
node3 := &Node{Val: 3}
node4 := &Node{Val: 4}
node5 := &Node{Val: 5}
node1.Next = node2
node2.Next = node3
node3.Next = node4
node4.Next = node5
fmt.Println("Исходный список:")
printLinkedList(node1)
reversedHead := reverseLinkedList(node1)
fmt.Println("Обращенный список:")
printLinkedList(reversedHead)
}
Пишите свое решение в комментариях👇
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
⚽️ Задача: Где приземлится мяч
Сложность: Средняя
Условие задачи: Дан двумерный массив, определяющий короб, а также
Каждая ячейка данной коробки имеет диагональную перегородку, которая может перенаправлять движение мяча.
- Перегородка ячейки типа "левый верхний угол —> правый нижний угол" имеет представление 1.
- Перегородка ячейки типа "правый верхний угол —> левый нижний угол" имеет представление -1.
В каждом столбце сверху бросается ровно один мяч, а дорога из перегородок может уткнуть мяч либо в стену, либо дать спокойно выпасть снизу коробки.
Необходимо вернуть массив, который будет показывать добрался ли
Пример:
Ввод: grid = [[1,1,1,-1,-1],[1,1,1,-1,-1],[-1,-1,-1,1,1],[1,1,1,1,-1],[-1,-1,-1,-1,-1]]
Вывод: [1,-1,-1,-1,-1]
Объяснение: *во вложении
Ввод: grid = [[-1]]
Вывод: [-1]
Объяснение: мяч уткнется в левую стенку коробки
📌 Решение
Пишите свое решение в комментариях👇
@golang_interview
Сложность: Средняя
Условие задачи: Дан двумерный массив, определяющий короб, а также
n-ое
количество мячей.Каждая ячейка данной коробки имеет диагональную перегородку, которая может перенаправлять движение мяча.
- Перегородка ячейки типа "левый верхний угол —> правый нижний угол" имеет представление 1.
- Перегородка ячейки типа "правый верхний угол —> левый нижний угол" имеет представление -1.
В каждом столбце сверху бросается ровно один мяч, а дорога из перегородок может уткнуть мяч либо в стену, либо дать спокойно выпасть снизу коробки.
Необходимо вернуть массив, который будет показывать добрался ли
i-ый
мяч до дна коробки (интерпретируется 1) или же уткнулся в стену (-1).Пример:
Ввод: grid = [[1,1,1,-1,-1],[1,1,1,-1,-1],[-1,-1,-1,1,1],[1,1,1,1,-1],[-1,-1,-1,-1,-1]]
Вывод: [1,-1,-1,-1,-1]
Объяснение: *во вложении
Ввод: grid = [[-1]]
Вывод: [-1]
Объяснение: мяч уткнется в левую стенку коробки
📌 Решение
Пишите свое решение в комментариях👇
@golang_interview
Параллельные тесты
Параллельные тесты в #golang позволяют выполнять несколько тестов одновременно. Это особенно полезно для тестов, связанных с IO поскольку другие тесты могут выполняться во время периодов ожидания, а значит, вы будете меньше времени ждать выполнения вашего набора тестов.
Это также поможет вам убедиться в том, что тесты не используют глобальное состояние, иначе они станут нестабильными.
Для этого достаточно пометить тест как параллельный следующим образом: изображение 1.
Бенчмарк-тесты
Бенчмарк-тесты - это отличный способ измерить и оптимизировать эффективность определенных частей кода.
Например, вот два способа конкатенации строки.
С помощью +: изображение 2.
Использование strings.Builder: изображение 3.
Если мы их запустим код, то получим следующий результат:
BenchmarkStringConcat-12 1000000 1200 ns/op BenchmarkStringBuilder-12 5000000 250 ns/op
Это означает, что тест выполнялся за
1000000
и 5000000
итераций, при этом stringConcat затрачивалось 1200 наносекунд на операцию, а strings.Builder - 250. Таким образом, strings.Builder гораздо эффективнее.@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🦫Улучшенная маршрутизация HTTP-серверов в Go 1.22
В Go 1.22 ожидается появление расширенного мультиплексора для обработки HTTP в пакете net/http.
Новый мультиплексор позволит сопоставлять шаблоны путей более гибко, что раньше требовало использования сторонних библиотек, таких как gorilla/mux.
Использование нового mux
Если вы когда-либо использовали сторонние пакеты mux/маршрутизаторов для Go (например, gorilla/mux), то использование нового стандартного mux будет простым и привычным. Начните с чтения документации по нему - она краткая и понятная.
Давайте рассмотрим несколько базовых примеров использования. Наш первый пример демонстрирует некоторые из новых возможностей mux по сопоставлению шаблонов:
Опытные программисты на Go сразу же заметят две новые особенности:
- В первом обработчике метод HTTP (в данном случае GET) указывается явно в составе шаблона. Это означает, что данный обработчик сработает только для GET-запросов к путям, начинающимся с /path/, а не для других HTTP-методов.
- Во втором обработчике во втором компоненте пути присутствует подстановочный знак - {id}, который ранее не поддерживался. Подстановочный знак будет соответствовать одному компоненту пути, и обработчик сможет получить доступ к найденному значению через метод PathValue запроса.
Поскольку Go 1.22 еще не выпущен, я рекомендую запускать этот пример с gotip. Полный пример кода с инструкциями по его выполнению. Давайте проверим работу этого сервера:
📌 Читать дальше
@golang_interview
В Go 1.22 ожидается появление расширенного мультиплексора для обработки HTTP в пакете net/http.
Новый мультиплексор позволит сопоставлять шаблоны путей более гибко, что раньше требовало использования сторонних библиотек, таких как gorilla/mux.
Использование нового mux
Если вы когда-либо использовали сторонние пакеты mux/маршрутизаторов для Go (например, gorilla/mux), то использование нового стандартного mux будет простым и привычным. Начните с чтения документации по нему - она краткая и понятная.
Давайте рассмотрим несколько базовых примеров использования. Наш первый пример демонстрирует некоторые из новых возможностей mux по сопоставлению шаблонов:
package main
import (
"fmt"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /path/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "got path\n")
})
mux.HandleFunc("/task/{id}/", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
fmt.Fprintf(w, "handling task with id=%v\n", id)
})
http.ListenAndServe("localhost:8090", mux)
}
Опытные программисты на Go сразу же заметят две новые особенности:
- В первом обработчике метод HTTP (в данном случае GET) указывается явно в составе шаблона. Это означает, что данный обработчик сработает только для GET-запросов к путям, начинающимся с /path/, а не для других HTTP-методов.
- Во втором обработчике во втором компоненте пути присутствует подстановочный знак - {id}, который ранее не поддерживался. Подстановочный знак будет соответствовать одному компоненту пути, и обработчик сможет получить доступ к найденному значению через метод PathValue запроса.
Поскольку Go 1.22 еще не выпущен, я рекомендую запускать этот пример с gotip. Полный пример кода с инструкциями по его выполнению. Давайте проверим работу этого сервера:
📌 Читать дальше
@golang_interview
Вышел GigaChat нового поколения. Разработчики @gigachat_bot качественно обновили его, изменив свой подход к обучению. Благодаря этому сервис стал лучше отвечать на запросы пользователей — примерно в два раза. При этом GigaChat также запустили в VK, аудитория сервиса уже достигла более 1 млн пользователей.
Попробовать.
@golang_interview
Попробовать.
@golang_interview
Условие: дано дерево (т.е. связный неориентированный граф, не имеющий циклов), состоящее из n узлов с числом от 0 до n - 1 и ровно n - 1 ребер. Корнем дерева является узел 0, и каждый узел дерева имеет метку, которая представляет собой символ нижнего регистра, указанный в строковых метках (т.е. узел с номером i имеет метку labels[i]).
Массив ребер задан на ребрах фермы[i] = [ai, bi], что означает наличие ребра между узлами ai и bi в дереве.
Возвращает массив размера n, где и[i] - количество узлов в поддереве узла земли, которые имеют ту же метку, что и узел i.
Поддерево дерева - это дерево, состоящее из узла в T и всех его дочерних узлов.
Пример:
Ввод: n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], labels = "abaedcd"
Вывод: [2,1,1,1,1,1,1]
Объяснение:
Ввод: n = 4, edges = [[0,1],[1,2],[0,3]], labels = "bbbb"
Вывод: [4,2,1,1]
📌 Решение задачи
Пишите свое решение в комментариях👇
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
6️⃣ Популярных стилей архитектуры API, которые необходимо знать.
1. gRPC — это система удалённого вызова процедур с открытым исходным кодом, в качестве транспорта используется HTTP/2, в качестве языка описания интерфейса — Protocol Buffers. gRPC предоставляет такие функции как аутентификация, двунаправленная потоковая передача и управление потоком, блокирующие или неблокирующие привязки, а также отмена и тайм-ауты. Генерирует кроссплатформенные привязки клиента и сервера для многих языков. Чаще всего используется для подключения служб в микросервисном стиле архитектуры и подключения мобильных устройств и браузерных клиентов к серверным службам.
2. SOAP: Протокол для обмена структурированной информацией при реализации веб-сервисов, известный своими строгими стандартами и форматом сообщений на основе XML.
3. GraphQL: Язык запросов и среда выполнения для API, позволяющая клиентам запрашивать только те данные, которые им необходимы, что уменьшает избыточную и недостаточную выборку данных.
4. Webhook: Механизм взаимодействия в реальном времени, при котором приложение отправляет HTTP POST-запросы на заранее определенный URL-адрес для уведомления и запуска действий в другой системе.
5. REST: Representational State Transfer - архитектурный стиль проектирования сетевых приложений, использующий стандартные методы HTTP (GET, POST, PUT, DELETE) для манипулирования ресурсами.
6. WebSocket: Протокол, обеспечивающий двунаправленную связь между клиентом и сервером в реальном времени через одно долговременное соединение. Идеально подходит для приложений, требующих обновления данных с малой задержкой, таких как чат или игры.
#junior
@golang_interview
1. gRPC — это система удалённого вызова процедур с открытым исходным кодом, в качестве транспорта используется HTTP/2, в качестве языка описания интерфейса — Protocol Buffers. gRPC предоставляет такие функции как аутентификация, двунаправленная потоковая передача и управление потоком, блокирующие или неблокирующие привязки, а также отмена и тайм-ауты. Генерирует кроссплатформенные привязки клиента и сервера для многих языков. Чаще всего используется для подключения служб в микросервисном стиле архитектуры и подключения мобильных устройств и браузерных клиентов к серверным службам.
2. SOAP: Протокол для обмена структурированной информацией при реализации веб-сервисов, известный своими строгими стандартами и форматом сообщений на основе XML.
3. GraphQL: Язык запросов и среда выполнения для API, позволяющая клиентам запрашивать только те данные, которые им необходимы, что уменьшает избыточную и недостаточную выборку данных.
4. Webhook: Механизм взаимодействия в реальном времени, при котором приложение отправляет HTTP POST-запросы на заранее определенный URL-адрес для уведомления и запуска действий в другой системе.
5. REST: Representational State Transfer - архитектурный стиль проектирования сетевых приложений, использующий стандартные методы HTTP (GET, POST, PUT, DELETE) для манипулирования ресурсами.
6. WebSocket: Протокол, обеспечивающий двунаправленную связь между клиентом и сервером в реальном времени через одно долговременное соединение. Идеально подходит для приложений, требующих обновления данных с малой задержкой, таких как чат или игры.
#junior
@golang_interview
FSRouter - это простая библиотека маршрутизатора файловой системы для Go, предназначенная для простой интеграции с большинством библиотек маршрутизаторов http. Она использует соглашение "NextJS" для получения маршрутов непосредственно в виде иерархии файлов директорий.
▪ Github
@golang_interview
go get -v -u github.com/aziis98/go-fsrouter
pages/
├── dashboard/[...all].html # => /dashboard/* (useful for SPAs)
└── user/
├── [name].html # => /user/:name
└── [name]/
└── posts/
└── [post].html # => /user/:name/posts/:post
▪ Github
@golang_interview