Created
October 13, 2024 07:09
-
-
Save revilon1991/e57b27a5a5655c27d081a4a3ced7cdc6 to your computer and use it in GitHub Desktop.
Golang API, WaitGroup, Semaphore, Cancel Context, Recovery Panic, Safe Map Mutex Result goroutine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"encoding/json" | |
"fmt" | |
"net/http" | |
"runtime/debug" | |
"strconv" | |
"sync" | |
) | |
const ( | |
semaphoreFrequency = 10 | |
) | |
func handler(w http.ResponseWriter, r *http.Request) { | |
var wg sync.WaitGroup | |
sem := &semaphore{c: make(chan struct{}, semaphoreFrequency)} | |
tInfos := &testInfos{m: make(map[string]string)} | |
ctx, cancel := context.WithCancel(context.Background()) | |
defer cancel() | |
goroutines := []string{"1", "2", "3", "4", "5", "6", "7", "8", "9"} | |
for i, _ := range goroutines { | |
wg.Add(1) | |
go func(i int) { | |
defer sem.release() | |
defer wg.Done() | |
defer func() { | |
if r := recover(); r != nil { | |
fmt.Printf("recovered from panic: %v\n%s\n", r, debug.Stack()) | |
cancel() | |
tInfos.set(strconv.Itoa(i), "err "+strconv.Itoa(i)) | |
} | |
}() | |
sem.acquire() | |
select { | |
case <-ctx.Done(): | |
tInfos.set(strconv.Itoa(i), "skip "+strconv.Itoa(i)) | |
default: | |
do(i, tInfos) | |
} | |
}(i) | |
} | |
wg.Wait() | |
w.Header().Set("Content-Type", "application/json") | |
w.WriteHeader(http.StatusOK) | |
_ = json.NewEncoder(w).Encode(struct { | |
Code int `json:"code"` | |
Result []string `json:"result"` | |
}{ | |
Code: http.StatusOK, | |
Result: tInfos.values(), | |
}) | |
} | |
func main() { | |
http.HandleFunc("/", handler) | |
fmt.Println("Server is running http://localhost:8080") | |
http.ListenAndServe(":8080", nil) | |
} | |
func do(i int, t *testInfos) { | |
//time.Sleep(1 * time.Second) | |
if i == 2 { | |
panic("panic " + strconv.Itoa(i)) | |
} | |
t.set(strconv.Itoa(i), "Done "+strconv.Itoa(i)) | |
} | |
type testInfos struct { | |
mu sync.Mutex | |
m map[string]string | |
} | |
func (idi *testInfos) set(index string, value string) { | |
idi.mu.Lock() | |
defer idi.mu.Unlock() | |
idi.m[index] = value | |
} | |
func (idi *testInfos) get(index string) (string, bool) { | |
idi.mu.Lock() | |
defer idi.mu.Unlock() | |
value, ok := idi.m[index] | |
return value, ok | |
} | |
func (idi *testInfos) len() int { | |
idi.mu.Lock() | |
defer idi.mu.Unlock() | |
return len(idi.m) | |
} | |
func (idi *testInfos) values() []string { | |
idi.mu.Lock() | |
defer idi.mu.Unlock() | |
values := make([]string, 0, len(idi.m)) | |
for _, value := range idi.m { | |
values = append(values, value) | |
} | |
return values | |
} | |
type semaphore struct { | |
c chan struct{} | |
} | |
func (s *semaphore) acquire() { | |
s.c <- struct{}{} | |
} | |
func (s *semaphore) release() { | |
<-s.c | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment