Ontwikkel een Go-applicatie met contextbeheer voor geavanceerde controle
description
Met deze prompt leer je hoe je contextbeheer in Go kunt toepassen voor betere controle over gelijktijdige processen, waardoor je applicaties robuuster en responsiever worden. Het helpt problemen met onbeheerde goroutines en resource leaks te voorkomen, wat beter is dan eenvoudige foutafhandeling of basisconcurrentie.
prompt
Help me een Go-applicatie te ontwikkelen die gebruikmaakt van contextbeheer voor het afhandelen van deadlines, annuleringen en time-outs in concurrente processen. Leg uit h ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een stapsgewijze uitleg over het gebruik van contexten in Go, inclusief een voorbeeld voor jouw webcrawler scenario:
1. Context maken:
Gebruik `context.Background()` of `context.WithTimeout()` om een context te creëren. Voor jouw scenario, waarin de crawler binnen 10 seconden moet stoppen als de server niet reageert, is `context.WithTimeout()` geschikt.
2. Context doorgeven:
Geef de context door aan functies die mogelijk lang duren of die je wilt kunnen annuleren, zoals HTTP-verzoeken of andere bewerkingen.
3. Context afhandelen:
Controleer de context op annulering of deadline door `ctx.Done()` te lezen, of door `ctx.Err()` te gebruiken.
Hier is een voorbeeldcode voor jouw webcrawler:
```go
package main
import (
"context"
"fmt"
"net/http"
"time"
)
func main() {
// Maak een context met een timeout van 10 seconden
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() // Zorg dat resources vrijgegeven worden
url := "http://voorbeeld.com" // Vervang door de echte URL
// Start de crawl met de context
err := crawl(ctx, url)
if err != nil {
fmt.Println("Crawling gestopt:", err)
} else {
fmt.Println("Crawling voltooid")
}
}
// crawl voert een HTTP GET uit en stopt als de context geannuleerd wordt
func crawl(ctx context.Context, url string) error {
// Maak een HTTP request met de context
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}
client := &http.Client{}
// Voer het verzoek uit
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// Hier zou je de inhoud verwerken
// Bijvoorbeeld: lees de body
// _, err = io.Copy(os.Stdout, resp.Body)
// if err != nil {
// return err
// }
// Voor dit voorbeeld simuleren we een bewerking die mogelijk lang duurt
select {
case <-time.After(5 * time.Second):
// Simulatie van verwerkingstijd
return nil
case <-ctx.Done():
// Context is geannuleerd of deadline bereikt
return ctx.Err()
}
}
```
**Samenvatting:**
- Maak een context met `context.WithTimeout()` voor de maximale tijd.
- Geef de context door aan alle bewerkingen die je wilt kunnen annuleren.
- Controleer `ctx.Done()` of gebruik `http.NewRequestWithContext()` om automatisch te stoppen bij annulering of timeout.
- Zorg dat je `defer cancel()` gebruikt om resources vrij te geven.
Op deze manier beheer je efficiënt deadlines en annuleringen in je Go-webcrawler!
provider: deepseek
model: deepseek-chat
Zeker, ik help je graag met het ontwikkelen van een Go-webcrawler met contextbeheer. Hier is een complete uitleg en implementatie:
## Contextbeheer in Go
### 1. Context aanmaken
```go
package main
import (
"context"
"fmt"
"net/http"
"time"
"sync"
)
func main() {
// Context met 10 seconden timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() // Zorgt voor proper cleanup
startCrawler(ctx)
}
```
### 2. Webcrawler met context doorgeven
```go
func startCrawler(ctx context.Context) {
urls := []string{
"https://example.com",
"https://example.org",
"https://example.net",
}
var wg sync.WaitGroup
results := make(chan string, len(urls))
for _, url := range urls {
wg.Add(1)
go crawlURL(ctx, &wg, url, results)
}
// Wacht op alle goroutines of context cancellation
go func() {
wg.Wait()
close(results)
}()
// Verzamel resultaten
for result := range results {
fmt.Println(result)
}
}
```
### 3. Crawl-functie met context handling
```go
func crawlURL(ctx context.Context, wg *sync.WaitGroup, url string, results chan<- string) {
defer wg.Done()
// Maak HTTP request met context
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
results <- fmt.Sprintf("Fout bij aanvraag %s: %v", url, err)
return
}
client := &http.Client{
Timeout: 5 * time.Second, // Individuele request timeout
}
// Voer request uit
resp, err := client.Do(req)
// Controleer of context geannuleerd is
select {
case <-ctx.Done():
results <- fmt.Sprintf("Geannuleerd: %s - %v", url, ctx.Err())
return
default:
// Doorgaan als context niet geannuleerd is
}
if err != nil {
results <- fmt.Sprintf("Fout: %s - %v", url, err)
return
}
defer resp.Body.Close()
results <- fmt.Sprintf("Success: %s - Status: %d", url, resp.StatusCode)
}
```
### 4. Verbeterde versie met error handling
```go
func advancedCrawler(ctx context.Context) {
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
urls := []string{"https://example.com", "https://example.org"}
for _, url := range urls {
select {
case <-ctx.Done():
fmt.Println("Crawler gestopt:", ctx.Err())
return
default:
result := fetchWithRetry(ctx, url, 3)
fmt.Println(result)
}
}
}
func fetchWithRetry(ctx context.Context, url string, maxRetries int) string {
for attempt := 1; attempt <= maxRetries; attempt++ {
select {
case <-ctx.Done():
return fmt.Sprintf("Geannuleerd: %s", url)
default:
result, err := fetchURL(ctx, url)
if err == nil {
return result
}
if attempt < maxRetries {
time.Sleep(time.Duration(attempt) * time.Second)
}
}
}
return fmt.Sprintf("Mislukt na %d pogingen: %s", maxRetries, url)
}
func fetchURL(ctx context.Context, url string) (string, error) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return "", err
}
client := http.Client{Timeout: 3 * time.Second}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
return fmt.Sprintf("Success: %s (%d)", url, resp.StatusCode), nil
}
```
## Belangrijke concepten:
### Context types:
- `context.Background()` - Basis context
- `context.WithTimeout()` - Timeout na bepaalde tijd
- `context.WithCancel()` - Handmatige annulering
- `context.WithDeadline()` - Specifieke eindtijd
### Best practices:
1. **Always pass context as first parameter**
2. **Check `ctx.Done()` in lange operaties**
3. **Use `defer cancel()` voor proper cleanup**
4. **Propageer context naar downstream calls**
### Context monitoring:
```go
func monitorContext(ctx context.Context) {
go func() {
<-ctx.Done()
fmt.Println("Context geannuleerd:", ctx.Err())
}()
}
```
Deze implementatie zorgt ervoor dat je webcrawler:
- Stopt na 10 seconden totaal
- Individuele requests timeouten na 5 seconden
- Proper afhandelt bij annuleringen
- Resources goed opruimt
Run met: `go run crawler.go`