Golang Portal
8.13K subscribers
429 photos
27 videos
7 files
458 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для Golang-разработчика

Связь: @devmangx
Download Telegram
Нереально большое количество полезных ресурсов по Go

Здесь масса ссылок на разные туториалы, гайды, примеры практического использования Go
Уверен, каждый найдёт здесь ответы на многие свои вопросы

Ссылка: тык

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍2
Неожиданные побочные эффекты при использовании append

Работа со срезами в Go кажется простой, но функции, такие как append, могут приводить к неожиданным побочным эффектам, если не учитывать их особенностей

Пример:
func modifySlice(slice []int) {
slice = append(slice, 4)
fmt.Println("Inside function:", slice) // [1, 2, 3, 4]
}

func main() {
originalSlice := []int{1, 2, 3}
modifySlice(originalSlice)
fmt.Println("Outside function:", originalSlice) // [1, 2, 3]
}

На первый взгляд может показаться, что вызов append внутри функции изменит исходный срез. Но это не так! Причина в том, что append может создать новый массив, если емкости исходного среза недостаточно, и вернуть ссылку на новый массив, оставляя оригинальный срез неизменным

Как исправить:

Чтобы избежать путаницы и явно модифицировать исходный срез, передавайте указатель на срез:
func modifySlice(slice *[]int) {
*slice = append(*slice, 4)
fmt.Println("Inside function:", *slice) // [1, 2, 3, 4]
}

func main() {
originalSlice := []int{1, 2, 3}
modifySlice(&originalSlice)
fmt.Println("Outside function:", originalSlice) // [1, 2, 3, 4]
}


Важные моменты:

🔹append может изменить размер и емкость среза. Если емкости хватает, исходный массив модифицируется; если нет — создаётся новый массив.
🔹Чтобы избежать побочных эффектов, помните, что срезы — это ссылки на массивы, но функции, такие как append, могут менять поведение

⚡️Советы:

🔹Если нужно модифицировать исходный срез, работайте с указателями.
🔹Учитывайте, что append не гарантирует модификацию оригинального массива, если емкость среза исчерпана.

👉 @juniorGolang | #заметки
Please open Telegram to view this post
VIEW IN TELEGRAM
👍133👀2🤯1
Функция Join пакета errors конкатенирует список ошибок и возвращает ошибку, если хотя бы одна из переданных ошибок не nil.

Join возвращает nil, если все переданные ошибки равны nil.

#tip by Golangbot

👉 @juniorGolang | #tips
Please open Telegram to view this post
VIEW IN TELEGRAM
👍122🤔2
Затенение переменных

Затенение переменных — одна из частых ошибок в Go, которая может привести к неожиданным последствиям. Пример:
var client *http.Client
if tracing {
client, err := createClientWithTracing()
if err != nil {
return err
}
log.Println(client)
} else {
client, err := createDefaultClient()
if err != nil {
return err
}
log.Println(client)
}


Внутри блоков if и else переменная client заново объявляется с помощью оператора :=, из-за чего внешняя переменная client остаётся неинициализированной. В итоге это приводит к ошибке, ведь внешняя переменная всё ещё равна nil

Как исправить?

1️⃣ Использовать другую переменную во внутренних блоках:
var client *http.Client
if tracing {
c, err := createClientWithTracing()
if err != nil {
return err
}
client = c
} else {
c, err := createDefaultClient()
if err != nil {
return err
}
client = c
}


2️⃣ Или присваивать напрямую:
var client *http.Client
var err error
if tracing {
client, err = createClientWithTracing()
} else {
client, err = createDefaultClient()
}
if err != nil {
return err
}


Затенение переменных в Go может усложнять код и приводить к трудноуловимым багам. Лучше избегать подобных ситуаций, чтобы код был более предсказуемым и легко читаемым 👍

👉 @juniorGolang | #заметки
Please open Telegram to view this post
VIEW IN TELEGRAM
👍111🌚1👀1
This media is not supported in your browser
VIEW IN TELEGRAM
⚙️ ntcharts (Nimble Terminal Charts) — Go-инструмент для отображени гистограмм, линий, временных рядов и других диаграмм с помощью Bubble Tea.

В репозитории много примеров для вдохновения 👇

https://github.com/NimbleMarkets/ntcharts

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Запуск горутины без управления её завершением

Запуск горутины (go func()) без механизма её завершения может привести к утечкам ресурсов и непредсказуемому поведению приложения. Особенно это критично для долгоживущих приложений или сервисов с высоким уровнем конкурентности

Пример:
func process() {
go func() {
// Выполняется какая-то длительная задача
time.Sleep(5 * time.Second)
fmt.Println("Горутина завершена")
}()
}

Если процесс завершится раньше, горутина продолжит выполнение, что может привести к утечке памяти или нарушению логики программы.

Как избежать ошибки?

1️⃣ Используйте контекст (context.Context) для управления временем жизни:
func process(ctx context.Context) {
go func() {
select {
case <-ctx.Done():
fmt.Println("Горутина остановлена")
return
case <-time.After(5 * time.Second):
fmt.Println("Задача выполнена")
}
}()
}
}

func main() {
ctx, cancel := context.WithCancel(context.Background())
process(ctx)

// Завершаем процесс через 2 секунды
time.Sleep(2 * time.Second)
cancel()
time.Sleep(3 * time.Second) // Ждём, чтобы увидеть результат
}


2️⃣ Используйте sync.WaitGroup для координации завершения:
func process(wg *sync.WaitGroup) {
defer wg.Done()
time.Sleep(5 * time.Second)
fmt.Println("Задача завершена")
}

func main() {
var wg sync.WaitGroup
wg.Add(1)
go process(&wg)

wg.Wait() // Ждём завершения всех горутин
fmt.Println("Все задачи завершены")
}


Почему это важно?

Бесконтрольные горутины приводят к непредсказуемым утечкам памяти и нагружают приложение. Это одна из самых частых проблем в Go-программах, которую сложно диагностировать на поздних этапах.

👉 @juniorGolang
Please open Telegram to view this post
VIEW IN TELEGRAM
👍144🔥2
🔥 Разработка фуллстек веб-приложения на Go + React: туториал от Jetbrains

В первой части рассматривается разработка REST API и работа с базой данных.
👉 Часть 1

Вторая часть посвящена построению пользовательского интерфейса на React с Tailwind CSS.
👉 Часть 2

В третьей части происходит интеграция фронтенда и бэкенда, тестирование и подготовка приложения к продакшену.
👉 Часть 3

👉 @juniorGolang
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Каналы в Go: синхронизация и обмен данными

Каналы — это важная часть параллелизма в Go, предоставляющие механизм синхронизации и передачи данных между горутинами. Вот несколько ключевых приемов работы с каналами, которые помогут вам эффективно использовать их

1️⃣Каналы для синхронизации

Когда несколько горутин должны взаимодействовать или завершать выполнение последовательно, можно использовать каналы. Например, при помощи канала можно дождаться завершения одной горутины перед запуском другой:
done := make(chan bool)
go func() {
// Выполнение задачи
done <- true // Сигнал завершения
}()
<-done // Ожидание завершения

Канал done передает сигнал о завершении работы горутины, обеспечивая синхронизацию.

2️⃣ Каналы для передачи данных

Каналы позволяют обмениваться данными между горутинами. Вот пример, как одна горутина может передать число другой через канал:
numbers := make(chan int)
go func() {
numbers <- 42
}()
fmt.Println(<-numbers)

Это простая передача данных между двумя горутинами через канал numbers. Важное правило: одна горутина пишет в канал, другая — читает.

3️⃣ Буферизованные каналы

Буферизованные каналы позволяют записывать данные в канал без блокировки, если количество элементов меньше заданного буфера:
buffered := make(chan int, 2)
buffered <- 1
buffered <- 2

Буферизованный канал buffered на 2 элемента позволит записать два значения без ожидания их немедленного чтения другой горутиной.

4️⃣ Закрытие каналов

Закрытие канала важно, когда отправляющая горутина больше не собирается передавать данные:
close(numbers)

После закрытия канала, все попытки чтения из него продолжаются, пока не будут прочитаны все данные, после чего канал вернет нулевое значение для своего типа.

Каналы — мощный инструмент в Go для управления параллелизмом. Они обеспечивают простой и безопасный способ взаимодействия между горутинами, помогая создавать эффективные параллельные программы.

👉 @juniorGolang
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍52
⚙️ Визуализация покрытия кода Go в виде древовидной карты

Интересный способ визуализировать большие проекты с помощью результатов go test -coverprofile.

$ go install github.com/nikolaydubina/go-cover-treemap@latest
$ go test -coverprofile cover.out ./...
$ go-cover-treemap -coverprofile cover.out > out.svg


👉 GitHub

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍122
Замыкания = универсальность

В языке Go замыкания используются повсеместно, давая возможность гибко решать разные задачи, используя один и тот же механизм.

Например, рассмотрим работу с картой в пакете sync — sync.Map:

var m sync.Map
m.Store("john", 21)
m.Store("maria", 25)
m.Store("steve", 29)


Для итерации по карте есть метод Range с сигнатурой:

Range(f func(key, value any) bool)


Но что, если нам нужно, например, посчитать сумму всех значений карты? Кажется, метод Range напрямую не позволяет этого сделать. Однако, благодаря замыканиям, мы можем обойти это ограничение:

sum := 0
m.Range(func(key, value any) bool {
sum += value.(int)
return true
})


Анонимная функция, передаваемая в Range, использует внешнюю переменную sum как накопитель. Таким образом, не изменяя сигнатуру метода, можно добиться нужного поведения.

Замыкания дают мощный инструмент для гибкости в коде.

👉 @juniorGolang
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
💡 gRPC и Go на практике

Вы, вероятно, слышали о gRPC, если еще не использовали её. Она особенно популярна для межсервисной связи благодаря своей эффективности, языковой независимости и встроенной поддержке таких вещей, как MTLS.

Выше представлен простой пример начала работы с gRPC от Matt Boyle.

👉 @juniorGolang | #tip
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Полезные приемы форматирования

Вот несколько приемов форматирования, которые могут быть вам полезны:

1️⃣ Закавыченная строка

Используйте %q, чтобы вывести строковое значение в кавычках.

s := "Hello, World!"
fmt.Printf("%q\n", s)
// "Hello, World!"


2️⃣ Названия полей структуры

Используйте %+v, чтобы вывести названия полей структуры, а не только значения.

alice := person{"Alice", 25}
fmt.Printf("%+v\n", alice)
// {name:Alice age:25}


3️⃣ Тип значения

Используйте %T, чтобы вывести тип значения.

var val any
val = 42
fmt.Printf("%T: %v\n", val, val)
// int: 42

val = "Hello, World!"
fmt.Printf("%T: %v\n", val, val)
// string: Hello, World!

val = person{"Alice", 25}
fmt.Printf("%T: %v\n", val, val)
// main.person: {Alice 25}


4️⃣ Индекс аргумента

Можно явно указать, какой по порядку аргумент выводить. Полезно, если одно и то же значение выводится несколько раз (как в примере с val выше).

num := 42
fmt.Printf("%[1]T: %[1]v\n", num)
// int: 42


Нумерация с 1.

👉 @juniorGolang
Please open Telegram to view this post
VIEW IN TELEGRAM
👍158
Анонимная сеть в 100 строк кода на Go

Прошло уже более года с тех пор как я написал статью - Анонимная сеть в 200 строк кода на Go. Пересмотрев её однажды осенним вечером я понял насколько всё в ней было ужасно - начиная с самого поведения логики кода и заканчивая его избыточностью. Сев за ноутбук и потратив от силы 20 минут у меня получилось написать сеть всего в 100 строк кода, используя лишь и только стандартную библиотеку языка.


👉 Читать статью

👉 @juniorGolang | #cтатья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥9
Нашли для вас два классных ресурса, которые помогут разобраться в GIT

🔜 Learn Git Branching — это интерактивный учебник по Git, направленный на закрепление теории прохождением наглядной практики.

🔜 Oh My Git! — игра для обучения Git. Там визуализируются внутренние структуры репозиториев. Игра опенсорс, так что можно покопаться в исходниках

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
⚙️ ObjectBox Go — встроенная база данных, которую можно использовать как альтернативу SQLite, gorm и т. д

ObjectBox проста в использовании благодаря интуитивно понятному встроенному API:


id, err := box.Put(&Person{ FirstName: "Joe", LastName: "Green" })


👉 Документация
👉 GitHub

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11
В чем сила пакета singleflight?

🔹singleflight предоставляет механизм подавления дублирующихся вызовов функций. Например, наше приложение запрашивает данные из API или базы данных.

🔹Если несколько запросов инициируют один и тот же вызов, это может привести к множественным идентичным вызовам к БД или API. Это создает нагрузку на систему, ведет к потерям CPU, памяти и пропускной способности сети.

🔹Matthew Boyle, автор Domain-Driven Design with Golang, приводит пример использования singleflight для устранения дублирующихся вызовов. В примере, несмотря на то, что 5 горутин одновременно запрашивают данные для одного и того же ключа, функция fetchData будет вызвана только один раз благодаря функции group.Do из пакета singleflight.

💡 singleflight также может используется в serverless кейсах. Google App Engine, например, применяет его как часть функции инициализации, поскольку там нет main.go.

👉 @juniorGolang | #tips
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
This media is not supported in your browser
VIEW IN TELEGRAM
Набор инструментов на Go для создания React-like GUI

Spot — это простой, кроссплатформенный, реактивный GUI-инструментарий для Go, использующий нативные виджеты там, где это возможно.
Большой акцент при разработке Spot был сделан на простоту использования и предоставление согласованного API на разных платформах

Ссылка: тык

👉 @juniorGolang | #ресурсы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91