🧠Почему context.WithCancel может вызвать утечку goroutine
context.WithCancel — удобный способ завершать операции, но если не вызывать cancel(), вы получите утечку. Причём не всегда это очевидно.
Посмотрим:
func handler(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithCancel(r.Context()) // cancel не вызывается! go doSomething(ctx) w.Write([]byte("done")) }
func doSomething(ctx context.Context) { select { case <-time.After(10 * time.Second): fmt.Println("done work") case <-ctx.Done(): fmt.Println("canceled") } }
Что здесь не так?
Если handler завершится раньше, чем doSomething, и cancel() не вызван — doSomething останется висеть, пока не истечёт r.Context()илиtime.After. И таких горутин может накопиться много, особенно при высоких нагрузках.
💡 Как избежать
1. Всегда вызывай cancel(), когда используешь context.WithCancel, даже если кажется, что это «не нужно».
2. Если передаёшь контекст в goroutine — убедись, что она завершится, даже если вызывающая функция ушла.
context.WithCancel — мощный инструмент. Но без вызова cancel() ты легко создашь утечку, которую не поймаешь ни в логах, ни в профилях — только под нагрузкой.
🧠Почему context.WithCancel может вызвать утечку goroutine
context.WithCancel — удобный способ завершать операции, но если не вызывать cancel(), вы получите утечку. Причём не всегда это очевидно.
Посмотрим:
func handler(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithCancel(r.Context()) // cancel не вызывается! go doSomething(ctx) w.Write([]byte("done")) }
func doSomething(ctx context.Context) { select { case <-time.After(10 * time.Second): fmt.Println("done work") case <-ctx.Done(): fmt.Println("canceled") } }
Что здесь не так?
Если handler завершится раньше, чем doSomething, и cancel() не вызван — doSomething останется висеть, пока не истечёт r.Context()илиtime.After. И таких горутин может накопиться много, особенно при высоких нагрузках.
💡 Как избежать
1. Всегда вызывай cancel(), когда используешь context.WithCancel, даже если кажется, что это «не нужно».
2. Если передаёшь контекст в goroutine — убедись, что она завершится, даже если вызывающая функция ушла.
context.WithCancel — мощный инструмент. Но без вызова cancel() ты легко создашь утечку, которую не поймаешь ни в логах, ни в профилях — только под нагрузкой.
Bitcoin is built on a distributed digital record called a blockchain. As the name implies, blockchain is a linked body of data, made up of units called blocks that contain information about each and every transaction, including date and time, total value, buyer and seller, and a unique identifying code for each exchange. Entries are strung together in chronological order, creating a digital chain of blocks. “Once a block is added to the blockchain, it becomes accessible to anyone who wishes to view it, acting as a public ledger of cryptocurrency transactions,” says Stacey Harris, consultant for Pelicoin, a network of cryptocurrency ATMs. Blockchain is decentralized, which means it’s not controlled by any one organization. “It’s like a Google Doc that anyone can work on,” says Buchi Okoro, CEO and co-founder of African cryptocurrency exchange Quidax. “Nobody owns it, but anyone who has a link can contribute to it. And as different people update it, your copy also gets updated.”
Telegram Auto-Delete Messages in Any Chat
Some messages aren’t supposed to last forever. There are some Telegram groups and conversations where it’s best if messages are automatically deleted in a day or a week. Here’s how to auto-delete messages in any Telegram chat. You can enable the auto-delete feature on a per-chat basis. It works for both one-on-one conversations and group chats. Previously, you needed to use the Secret Chat feature to automatically delete messages after a set time. At the time of writing, you can choose to automatically delete messages after a day or a week. Telegram starts the timer once they are sent, not after they are read. This won’t affect the messages that were sent before enabling the feature.