package main
import (
"context"
"fmt"
"sync"
"time"
)
func RunWorkers(n int) {
var wg sync.WaitGroup
for i := 0; i < n; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("Worker %d starting\n", id)
time.Sleep(100 * time.Millisecond)
fmt.Printf("Worker %d done\n", id)
}(i)
}
wg.Wait()
}
func ProduceConsume() {
ch := make(chan int, 10)
go func() {
for i := 0; i < 5; i++ {
ch <- i
fmt.Println("Produced:", i)
}
close(ch)
}()
for val := range ch {
fmt.Println("Consumed:", val)
}
}
func WorkerPool(jobs []int, workers int) []int {
jobCh := make(chan int, len(jobs))
resultCh := make(chan int, len(jobs))
var wg sync.WaitGroup
for w := 0; w < workers; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for job := range jobCh {
result := job * job
resultCh <- result
}
}()
}
go func() {
for _, job := range jobs {
jobCh <- job
}
close(jobCh)
}()
go func() {
wg.Wait()
close(resultCh)
}()
var results []int
for r := range resultCh {
results = append(results, r)
}
return results
}
func SelectDemo() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(100 * time.Millisecond)
ch1 <- "from ch1"
}()
go func() {
time.Sleep(200 * time.Millisecond)
ch2 <- "from ch2"
}()
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
case <-time.After(300 * time.Millisecond):
fmt.Println("timeout")
}
}
type Result struct {
Value int
Error error
}
func ProcessWithTimeout(ctx context.Context, items []int) ([]Result, error) {
results := make([]Result, len(items))
for i, item := range items {
select {
case <-ctx.Done():
return results, ctx.Err()
default:
time.Sleep(50 * time.Millisecond)
results[i] = Result{Value: item * 2}
}
}
return results, nil
}
func Generator(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
func Square(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}
func Merge(chans ...<-chan int) <-chan int {
var wg sync.WaitGroup
out := make(chan int)
output := func(c <-chan int) {
defer wg.Done()
for n := range c {
out <- n
}
}
wg.Add(len(chans))
for _, c := range chans {
go output(c)
}
go func() {
wg.Wait()
close(out)
}()
return out
}
type SafeCounter struct {
mu sync.RWMutex
count map[string]int
}
func NewSafeCounter() *SafeCounter {
return &SafeCounter{
count: make(map[string]int),
}
}
func (c *SafeCounter) Inc(key string) {
c.mu.Lock()
defer c.mu.Unlock()
c.count[key]++
}
func (c *SafeCounter) Get(key string) int {
c.mu.RLock()
defer c.mu.RUnlock()
return c.count[key]
}
type Singleton struct {
value string
}
var (
instance *Singleton
once sync.Once
)
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{value: "initialized"}
})
return instance
}
func main() {
jobs := []int{1, 2, 3, 4, 5}
results := WorkerPool(jobs, 3)
fmt.Println("Results:", results)
nums := Generator(1, 2, 3, 4, 5)
squares := Square(nums)
for n := range squares {
fmt.Println("Square:", n)
}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
items := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
res, err := ProcessWithTimeout(ctx, items)
if err != nil {
fmt.Println("Error:", err)
}
fmt.Println("Processed:", len(res))
}