🧠Почему 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() ты легко создашь утечку, которую не поймаешь ни в логах, ни в профилях — только под нагрузкой.
Secret Chats are one of the service’s additional security features; it allows messages to be sent with client-to-client encryption. This setup means that, unlike regular messages, these secret messages can only be accessed from the device’s that initiated and accepted the chat. Additionally, Telegram notes that secret chats leave no trace on the company’s services and offer a self-destruct timer.
How Does Bitcoin Work?
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.”