-
Notifications
You must be signed in to change notification settings - Fork 20
05 - Feat/sorting exercise #96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6326629
04d79c0
3696939
8f02373
3d54262
439f692
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package deferr | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "sync" | ||
| ) | ||
|
|
||
| var ( | ||
| fileInstance *os.File | ||
| once sync.Once | ||
| ) | ||
|
|
||
| func CreateFile() *os.File { | ||
| once.Do(func() { | ||
| f, err := os.CreateTemp("", "example.txt") | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| fileInstance = f | ||
| }) | ||
| return fileInstance | ||
| } | ||
|
|
||
| func WriteToFile(*os.File) { | ||
| f := CreateFile() | ||
| defer f.Close() | ||
| fmt.Fprintln(f, "data") | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package go_routines | ||
|
|
||
| import ( | ||
| "time" | ||
| ) | ||
|
|
||
| func sleepForOneHundredMillisecond() { | ||
| time.Sleep(100 * time.Millisecond) | ||
| } | ||
|
|
||
| func sleepForTwoHundredMilliseconds() { | ||
| time.Sleep(200 * time.Millisecond) | ||
| } | ||
|
|
||
| func RunConcurrently() { | ||
| go sleepForOneHundredMillisecond() | ||
| go sleepForTwoHundredMilliseconds() | ||
|
|
||
| // go func() { | ||
| // sleepForOneHundredMillisecond() | ||
| // }() | ||
| // go func() { | ||
| // sleepForTwoHundredMilliseconds() | ||
| // }() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package channels | ||
|
|
||
| func ReadMessage() string { | ||
| chat := make(chan string) | ||
| go func() { | ||
| senderMessage := "Hi!" | ||
| chat <- senderMessage | ||
| }() | ||
|
|
||
| msg := <-chat | ||
|
|
||
| return msg | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package mutexes | ||
|
|
||
| import "sync" | ||
|
|
||
| const numWorkers = 10_000 | ||
|
|
||
| func Counting() int { | ||
|
|
||
| count := 0 | ||
| done := make(chan bool, numWorkers) | ||
| var wg sync.WaitGroup | ||
| var mu sync.Mutex | ||
|
|
||
| for i := 1; i <= numWorkers; i++ { | ||
| wg.Add(1) | ||
| go func() { | ||
| defer wg.Done() | ||
| mu.Lock() | ||
| count += 1 | ||
| mu.Unlock() | ||
| done <- true | ||
| }() | ||
| } | ||
|
|
||
| for i := 1; i <= numWorkers; i++ { | ||
| <-done | ||
| } | ||
|
|
||
| wg.Wait() | ||
| return count | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package sorting | ||
|
|
||
| import ( | ||
| "slices" | ||
| ) | ||
|
|
||
| var Years = []int{2017, 2003, 2026} | ||
| var Pets = []string{"Dog", "Cat", "Parrot"} | ||
|
|
||
| func SortNumbers() []int { | ||
| slices.Sort(Years) | ||
| return Years | ||
| } | ||
|
|
||
| func SortAnimals() []string { | ||
| slices.Sort(Pets) | ||
| return Pets | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package deferr | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "sync" | ||
| ) | ||
|
|
||
| var ( | ||
| fileInstance *os.File | ||
| once sync.Once | ||
| ) | ||
|
|
||
| func CreateFile() *os.File { | ||
| once.Do(func() { | ||
| f, err := os.CreateTemp("", "example.txt") | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| fileInstance = f | ||
| }) | ||
| return fileInstance | ||
| } | ||
|
|
||
| func WriteToFile(*os.File) { | ||
| f := CreateFile() | ||
| // TODO: Add your code here | ||
| fmt.Fprintln(f, "data") | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package deferr | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "testing" | ||
| ) | ||
|
|
||
| func TestClosingFileAfterWriting(t *testing.T) { | ||
| f := CreateFile() | ||
| WriteToFile(f) | ||
|
|
||
| // trying to write to the file after closing | ||
| _, err := fmt.Fprintln(f, "data") | ||
| if err == nil { | ||
| t.Fatal("File wasn't closed!") | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package go_routines | ||
|
|
||
| import ( | ||
| "time" | ||
| ) | ||
|
|
||
| func sleepForOneHundredMillisecond() { | ||
| time.Sleep(100 * time.Millisecond) | ||
| } | ||
|
|
||
| func sleepForTwoHundredMilliseconds() { | ||
| time.Sleep(200 * time.Millisecond) | ||
| } | ||
|
|
||
| func RunConcurrently() { | ||
| // TODO: update following code | ||
| sleepForOneHundredMillisecond() | ||
| sleepForTwoHundredMilliseconds() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package go_routines | ||
|
|
||
| import ( | ||
| "testing" | ||
| "time" | ||
| ) | ||
|
|
||
| func TestGoRoutines(t *testing.T) { | ||
| start := time.Now() | ||
| RunConcurrently() | ||
| elapsed := time.Since(start) | ||
|
|
||
| // according to benchmark it is about ~2 microseconds | ||
| // x2 for more breathing room, so 4 | ||
| if elapsed.Microseconds() >= 4 { | ||
| t.Fatal("Go routines was not used!") | ||
| } | ||
| } | ||
|
|
||
| func BenchmarkRunConcurrently(b *testing.B) { | ||
| for i := 0; i < b.N; i++ { | ||
| RunConcurrently() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package channels | ||
|
|
||
| import "fmt" | ||
|
|
||
| func ReadMessage() string { | ||
| // TODO: update following code | ||
| // to receive senderMessage in main goroutine | ||
| // and return it from ReadMessage function | ||
| go func() { | ||
| senderMessage := "Hi!" | ||
| fmt.Println(senderMessage) | ||
| }() | ||
|
|
||
| return "" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package channels | ||
|
|
||
| import "testing" | ||
|
|
||
| func TestReadMessage(t *testing.T) { | ||
| got := ReadMessage() | ||
| want := "Hi!" | ||
|
|
||
| if got != want { | ||
| t.Errorf("Expected %s, got %s", want, got) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| package mutexes | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| import "sync" | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const numWorkers = 10_000 | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| func Counting() int { | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // TODO: update following code to avoid race conditions | ||||||||||||||||||||||||||||||||||||||||||||||
| // using sync.Mutex | ||||||||||||||||||||||||||||||||||||||||||||||
| count := 0 | ||||||||||||||||||||||||||||||||||||||||||||||
| done := make(chan bool, numWorkers) | ||||||||||||||||||||||||||||||||||||||||||||||
| var wg sync.WaitGroup | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| for i := 1; i <= numWorkers; i++ { | ||||||||||||||||||||||||||||||||||||||||||||||
| wg.Add(1) | ||||||||||||||||||||||||||||||||||||||||||||||
| go func() { | ||||||||||||||||||||||||||||||||||||||||||||||
| defer wg.Done() | ||||||||||||||||||||||||||||||||||||||||||||||
| count += 1 | ||||||||||||||||||||||||||||||||||||||||||||||
| done <- true | ||||||||||||||||||||||||||||||||||||||||||||||
| }() | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Synchronize the shared counter to avoid races.
count := 0
done := make(chan bool, numWorkers)
var wg sync.WaitGroup
+ var mu sync.Mutex
for i := 1; i <= numWorkers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
- count += 1
+ mu.Lock()
+ count++
+ mu.Unlock()
done <- true
}()
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| for i := 1; i <= numWorkers; i++ { | ||||||||||||||||||||||||||||||||||||||||||||||
| <-done | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| wg.Wait() | ||||||||||||||||||||||||||||||||||||||||||||||
| return count | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package mutexes | ||
|
|
||
| import "testing" | ||
|
|
||
| func TestCounter(t *testing.T) { | ||
| got := Counting() | ||
| want := numWorkers | ||
|
|
||
| if got != want { | ||
| t.Fatalf("Expected %d, got %d", want, got) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package sorting | ||
|
|
||
| var Years = []int{2017, 2003, 2026} | ||
| var Pets = []string{"Dog", "Cat", "Parrot"} | ||
|
|
||
| func SortNumbers() []int { | ||
| // TODO: sort Years | ||
| return Years | ||
| } | ||
|
|
||
| func SortAnimals() []string { | ||
| // TODO: sort Pets | ||
| return Pets | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package sorting | ||
|
|
||
| import ( | ||
| "slices" | ||
| "testing" | ||
| ) | ||
|
|
||
| func TestSorting(t *testing.T) { | ||
| t.Run("Sorting numbers", func(t *testing.T) { | ||
| SortNumbers() | ||
| if !slices.IsSorted(Years) { | ||
| t.Fatal("Strings are not sorted!") | ||
| } | ||
| }) | ||
|
|
||
| t.Run("Sorting strings", func(t *testing.T) { | ||
| SortAnimals() | ||
| if !slices.IsSorted(Pets) { | ||
| t.Fatal("Strings are not sorted!") | ||
| } | ||
| }) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor to avoid mutable global state.
Exported package-level variables that are mutated by the sorting functions create several issues:
Consider refactoring to accept input parameters and return new sorted slices:
Alternatively, if in-place sorting is the intended teaching point, document this behavior clearly and accept the slice as a parameter.
🤖 Prompt for AI Agents