Skip to content

Commit 68bd480

Browse files
committed
✨ add conc sample
0 parents  commit 68bd480

File tree

18 files changed

+698
-0
lines changed

18 files changed

+698
-0
lines changed

.github/workflows/go.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Go
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
jobs:
11+
build_and_test:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Setup go-task
15+
uses: pnorton5432/setup-task@v1
16+
with:
17+
task-version: 3.29.1
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
- name: Setup Go
21+
uses: actions/setup-go@v5
22+
with:
23+
go-version: 'stable'
24+
check-latest: true
25+
- name: Task Build for mage
26+
run: task build-gg
27+
- name: Test with gg build
28+
run: ./gg build

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work
22+
go.work.sum
23+
24+
# env file
25+
.env
26+
gg
27+
mage
28+
bin

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# golang-sample-with-conc
2+
3+
This repository is demo for use conc with golang concurrency handle
4+
5+
## install package
6+
7+
```shell
8+
go get github.com/sourcegraph/conc
9+
```
10+
11+
## samples
12+
13+
[simple-task](./cmd/simple-task/README.md)
14+
15+
[pool-sample](./cmd/pool-sample/README.md)
16+
17+
[aggregate-sample](./cmd/aggregate-sample/README.md)
18+
19+
[handle-context](./cmd/handle-context/README.md)
20+
21+
[handle-errors](./cmd/handle-errors/README.md)

Taskfile.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
version: '3'
2+
3+
tasks:
4+
default:
5+
cmds:
6+
- echo "This is task cmd"
7+
silent: true
8+
9+
# build:
10+
# cmds:
11+
# - CGO_ENABLED=0 GOOS=linux go build -o bin/main cmd/main.go
12+
# silent: true
13+
# run:
14+
# cmds:
15+
# - ./bin/main
16+
# deps:
17+
# - build
18+
# silent: true
19+
20+
build-mage:
21+
cmds:
22+
- CGO_ENABLED=0 GOOS=linux go build -o ./mage mage-tools/mage.go
23+
silent: true
24+
25+
build-gg:
26+
cmds:
27+
- ./mage -d mage-tools -compile ../gg
28+
deps:
29+
- build-mage
30+
silent: true
31+
32+
coverage:
33+
cmds:
34+
- go test -v -cover ./...
35+
silent: true
36+
test:
37+
cmds:
38+
- go test -v ./...
39+
silent: true
40+

cmd/aggregate-sample/README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# aggregate-sample
2+
3+
```golang
4+
package main
5+
6+
import (
7+
"fmt"
8+
"math/rand"
9+
"time"
10+
11+
"github.com/sourcegraph/conc/pool"
12+
)
13+
14+
// simulateAPI simulates an API call to fetech product prices
15+
func simulateAPI(apiID int) int {
16+
// Simulate varying response times
17+
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
18+
19+
// Generate a random duration
20+
randomDuration := time.Duration(rng.Int63n(int64(2 * time.Second)))
21+
22+
time.Sleep(randomDuration)
23+
24+
// Return a mock price
25+
return apiID*10 + rand.Intn(10)
26+
}
27+
28+
func main() {
29+
// Create a result pool
30+
pool := pool.NewWithResults[int]().WithMaxGoroutines(5)
31+
32+
// Simulate fetching prices
33+
for apiID := 1; apiID <= 10; apiID++ {
34+
apiID := apiID // Capture variable for goroutine
35+
pool.Go(func() int {
36+
fmt.Printf("Fetching price from API %d...\n", apiID)
37+
return simulateAPI(apiID)
38+
})
39+
}
40+
41+
// Wait for all API calls to finish
42+
prices := pool.Wait()
43+
// Display prices in the console
44+
fmt.Printf("Collected Prices: %v\n", prices)
45+
}
46+
```

cmd/aggregate-sample/main.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"math/rand"
6+
"time"
7+
8+
"github.com/sourcegraph/conc/pool"
9+
)
10+
11+
// simulateAPI simulates an API call to fetech product prices
12+
func simulateAPI(apiID int) int {
13+
// Simulate varying response times
14+
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
15+
16+
// Generate a random duration
17+
randomDuration := time.Duration(rng.Int63n(int64(2 * time.Second)))
18+
19+
time.Sleep(randomDuration)
20+
21+
// Return a mock price
22+
return apiID*10 + rand.Intn(10)
23+
}
24+
25+
func main() {
26+
// Create a result pool
27+
pool := pool.NewWithResults[int]().WithMaxGoroutines(5)
28+
29+
// Simulate fetching prices
30+
for apiID := 1; apiID <= 10; apiID++ {
31+
apiID := apiID // Capture variable for goroutine
32+
pool.Go(func() int {
33+
fmt.Printf("Fetching price from API %d...\n", apiID)
34+
return simulateAPI(apiID)
35+
})
36+
}
37+
38+
// Wait for all API calls to finish
39+
prices := pool.Wait()
40+
// Display prices in the console
41+
fmt.Printf("Collected Prices: %v\n", prices)
42+
}

cmd/handle-context/README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# handle-context
2+
3+
```golang
4+
package main
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"strings"
10+
"time"
11+
12+
"github.com/sourcegraph/conc/pool"
13+
)
14+
15+
// validateFile simulates file validation. It returns an error for invalid files
16+
func validateFile(fileName string) error {
17+
if strings.HasPrefix(fileName, "invalid") {
18+
return fmt.Errorf("validation failed for file: %s", fileName)
19+
}
20+
fmt.Printf("File %s validated successfully\n", fileName)
21+
return nil
22+
}
23+
func main() {
24+
// A list of files
25+
files := []string{
26+
"file1.csv",
27+
"invalid_file2.csv",
28+
"file3.csv",
29+
"file4.csv",
30+
"invalid_file5.csv",
31+
"file6.csv",
32+
}
33+
34+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
35+
defer cancel()
36+
// Create a new pool with error handling
37+
pool := pool.New().WithErrors().WithContext(ctx).WithMaxGoroutines(2)
38+
39+
// Add validation tasks for each file
40+
for _, file := range files {
41+
pool.Go(func(poolCtx context.Context) error {
42+
twoSecondTimerCh := time.After(2 * time.Second)
43+
select {
44+
case <-poolCtx.Done():
45+
fmt.Printf("Task cancelled\n")
46+
return poolCtx.Err()
47+
case <-twoSecondTimerCh:
48+
err := validateFile(file)
49+
return err
50+
}
51+
})
52+
}
53+
54+
// Wait for all tasks to finish
55+
if err := pool.Wait(); err != nil {
56+
fmt.Printf("Error: %v\n", err)
57+
} else {
58+
fmt.Println("All files validated successfully")
59+
}
60+
}
61+
62+
```

cmd/handle-context/main.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
"time"
8+
9+
"github.com/sourcegraph/conc/pool"
10+
)
11+
12+
// validateFile simulates file validation. It returns an error for invalid files
13+
func validateFile(fileName string) error {
14+
if strings.HasPrefix(fileName, "invalid") {
15+
return fmt.Errorf("validation failed for file: %s", fileName)
16+
}
17+
fmt.Printf("File %s validated successfully\n", fileName)
18+
return nil
19+
}
20+
func main() {
21+
// A list of files
22+
files := []string{
23+
"file1.csv",
24+
"invalid_file2.csv",
25+
"file3.csv",
26+
"file4.csv",
27+
"invalid_file5.csv",
28+
"file6.csv",
29+
}
30+
31+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
32+
defer cancel()
33+
// Create a new pool with error handling
34+
pool := pool.New().WithErrors().WithContext(ctx).WithMaxGoroutines(2)
35+
36+
// Add validation tasks for each file
37+
for _, file := range files {
38+
pool.Go(func(poolCtx context.Context) error {
39+
twoSecondTimerCh := time.After(2 * time.Second)
40+
select {
41+
case <-poolCtx.Done():
42+
fmt.Printf("Task cancelled\n")
43+
return poolCtx.Err()
44+
case <-twoSecondTimerCh:
45+
err := validateFile(file)
46+
return err
47+
}
48+
})
49+
}
50+
51+
// Wait for all tasks to finish
52+
if err := pool.Wait(); err != nil {
53+
fmt.Printf("Error: %v\n", err)
54+
} else {
55+
fmt.Println("All files validated successfully")
56+
}
57+
}

cmd/handle-errors/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# handle-errors
2+
3+
```golang
4+
package main
5+
6+
import (
7+
"fmt"
8+
"strings"
9+
10+
"github.com/sourcegraph/conc/pool"
11+
)
12+
13+
// validateFile simulates file validation. It returns an error for invalid files
14+
func validateFile(fileName string) error {
15+
if strings.HasPrefix(fileName, "invalid") {
16+
return fmt.Errorf("validation failed for file: %s", fileName)
17+
}
18+
fmt.Printf("File %s validated successfully\n", fileName)
19+
return nil
20+
}
21+
func main() {
22+
// A list of files
23+
files := []string{
24+
"file1.csv",
25+
"invalid_file2.csv",
26+
"file3.csv",
27+
"file4.csv",
28+
"invalid_file5.csv",
29+
"file6.csv",
30+
}
31+
32+
// Create a new pool with error handling
33+
pool := pool.New().WithErrors().WithMaxGoroutines(2)
34+
35+
// Add validation tasks for each file
36+
for _, file := range files {
37+
pool.Go(func() error {
38+
return validateFile(file)
39+
})
40+
}
41+
42+
// Wait for all tasks to finish
43+
if err := pool.Wait(); err != nil {
44+
fmt.Printf("Error: %v\n", err)
45+
} else {
46+
fmt.Println("All files validated successfully")
47+
}
48+
}
49+
50+
```

0 commit comments

Comments
 (0)