Хотите запутать новичка в #golang? Спросите их что выведет этот кода.
https://go.dev/play/p/K6Qo94a6_yU
@golangtests
https://go.dev/play/p/K6Qo94a6_yU
@golangtests
👎7👍5🤔3❤2😱2🔥1
💡 Go-хак дня:
Ключевое слово
Вот что с ним можно:
🔹 Создавать собственные типы на основе
🔹 Давать удобные псевдонимы стандартным типам
🔹 Прикреплять методы к любому типу — даже к обычному
Это позволяет писать чистый, читаемый и расширяемый код.
Управляй логикой через свои типы — и код начнёт работать на тебя 💪
#GoLang #GoTips #LearnGo
@golangtests
Ключевое слово
type
в Go — это мощный инструмент, а не просто способ объявить struct
.Вот что с ним можно:
🔹 Создавать собственные типы на основе
int
, string
, map
и т.д. 🔹 Давать удобные псевдонимы стандартным типам
🔹 Прикреплять методы к любому типу — даже к обычному
int
Это позволяет писать чистый, читаемый и расширяемый код.
Управляй логикой через свои типы — и код начнёт работать на тебя 💪
#GoLang #GoTips #LearnGo
@golangtests
❤7👍3🔥3
💡 Вместо отправки сигнала в канал, подумай о
Оба варианта:
✅ Работают, даже если никто не читает из канала
✅ Позволяют нескольким горутинам реагировать на завершение
Такой подход делает код чище и избегает утечек.
#golang #concurrency
close()
или sync.WaitGroup
для завершения горутины.Оба варианта:
✅ Работают, даже если никто не читает из канала
✅ Позволяют нескольким горутинам реагировать на завершение
Такой подход делает код чище и избегает утечек.
#golang #concurrency
👍10🔥1
✅ В Go можно запускать тесты без единой внешней библиотеки — всё встроено из коробки!
Вот как протестировать код в 3 шага:
1️⃣ Создай файл с суффиксом
2️⃣ Импортируй пакет
3️⃣ Запусти тесты командой:
Никаких зависимостей. Никаких настроек. Просто пиши код и проверяй его сразу.
#golang #testing #unittest
Вот как протестировать код в 3 шага:
1️⃣ Создай файл с суффиксом
_test.go
— например, sum_test.go
2️⃣ Импортируй пакет
testing
и напиши функцию вида: TestXxx(t *testing.T)
3️⃣ Запусти тесты командой:
go test
Никаких зависимостей. Никаких настроек. Просто пиши код и проверяй его сразу.
#golang #testing #unittest
🤯11❤4👍4😁4🔥1
⚡ Полезный приём в Go — используем
Например, при загрузке ENV-переменных:
Теперь переменные окружения загружаются лишь один раз, а дальше берутся из памяти.
#golang #concurrency #tips
sync.Once
, чтобы инициализировать значение только один раз. Например, при загрузке ENV-переменных:
package config
import (
"os"
"sync"
)
var (
loadOnce sync.Once
envVars map[string]string
)
func GetEnvVars() map[string]string {
loadOnce.Do(func() {
envVars = map[string]string{
"DB_URL": os.Getenv("DB_URL"),
"API_KEY": os.Getenv("API_KEY"),
}
})
return envVars
}
Теперь переменные окружения загружаются лишь один раз, а дальше берутся из памяти.
#golang #concurrency #tips
👎9❤5👍2🔥1
🧩 Go Квиз: оцените отношение времени g()/f()
#Golang
Идея проста: какая из функций будет «дороже» и во сколько раз?
- f делает три умножения на итерацию плюс запись в массив. Это «дешёвая» арифметика с линейным проходом по памяти.
- g на каждой итерации создаёт срез a[:] и вызывает doNothing. Если компилятор встраивает пустую функцию и выкидывает бесполезный срез, тело цикла почти исчезает. Если запретить инлайнинг, вы получите N вызовов функции и накладные расходы на создание среза на каждой итерации.
Чего ожидать?
С инлайнингом и DCE: g() часто быстрее f(), потому что почти ничего не делает, тогда как f() реально пишет в память. Отношение g()/f() < 1.
Без инлайнинга: g() резко замедляется из-за стоимости вызова функции и построения среза на каждой итерации. Отношение g()/f() ≫ 1, иногда на порядок.
Вывод: результат зависит от оптимизаций компилятора. «Смысл» цикла, который не производит наблюдаемых эффектов, Go охотно выкидывает.
Как проверить у себя
Что запомнить
- Микробенчи в Go чувствительны к инлайнингу и dead-code elimination.
- Запись в память удерживает цикл «реальным», тогда как пустые вызовы и срезы могут исчезнуть.
- Измеряйте обе конфигурации: с оптимизациями и без, чтобы понять истинную стоимость.
Если коротко:
- В реальном билде с оптимизациями g()/f() обычно < 1.
- С запретом инлайнинга g()/f() обычно ≫ 1 из-за накладных расходов вызова.
#Golang
Идея проста: какая из функций будет «дороже» и во сколько раз?
const N = 1 << 12
func f(){
for a, i := [N]int{}, 0; i < len(a); i++ {
a[i] = i * i * i * i
}
}
func doNothing(a []int) {}
func g(){
for a, i := [N]int{}, 0; i < len(a); i++ {
doNothing(a[:])
}
}
- f делает три умножения на итерацию плюс запись в массив. Это «дешёвая» арифметика с линейным проходом по памяти.
- g на каждой итерации создаёт срез a[:] и вызывает doNothing. Если компилятор встраивает пустую функцию и выкидывает бесполезный срез, тело цикла почти исчезает. Если запретить инлайнинг, вы получите N вызовов функции и накладные расходы на создание среза на каждой итерации.
Чего ожидать?
С инлайнингом и DCE: g() часто быстрее f(), потому что почти ничего не делает, тогда как f() реально пишет в память. Отношение g()/f() < 1.
Без инлайнинга: g() резко замедляется из-за стоимости вызова функции и построения среза на каждой итерации. Отношение g()/f() ≫ 1, иногда на порядок.
Вывод: результат зависит от оптимизаций компилятора. «Смысл» цикла, который не производит наблюдаемых эффектов, Go охотно выкидывает.
Как проверить у себя
Копировать код
# обычный режим
go test -bench . -benchmem
# отключить инлайнинг -l, чтобы увидеть цену вызова функции
go test -gcflags='-l' -bench . -benchmem
Что запомнить
- Микробенчи в Go чувствительны к инлайнингу и dead-code elimination.
- Запись в память удерживает цикл «реальным», тогда как пустые вызовы и срезы могут исчезнуть.
- Измеряйте обе конфигурации: с оптимизациями и без, чтобы понять истинную стоимость.
Если коротко:
- В реальном билде с оптимизациями g()/f() обычно < 1.
- С запретом инлайнинга g()/f() обычно ≫ 1 из-за накладных расходов вызова.
👍1🔥1