-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Nested Goroutines | ||
|
||
In this exercise, you'll practice using contexts to manage nested goroutines in Go. Your task is to | ||
implement two functions: one that starts a long-running operation in a separate goroutine, and | ||
another that performs the actual long-running operation. You'll use contexts to manage the lifetime | ||
of these goroutines and implement a cancellation mechanism that allows the caller to stop both | ||
goroutines. | ||
|
||
The two function signatures: | ||
|
||
```go | ||
func StartTask(ctx context.Context) (result string, err error) | ||
func SubTask(ctx context.Context) (result string, err error) | ||
``` | ||
|
||
Requirements: | ||
|
||
1. `StartTask` should: | ||
- Create a new context with a 1-second timeout, derived from the input context. | ||
- Start `SubTask` in a new goroutine using the derived context. | ||
- If the main context is canceled, cancel the subtask and return with an empty string and the | ||
error provided by the main context (use [`ctx.Err()`](https://pkg.go.dev/context#Context)). | ||
- If `SubTask` finishes with a non-empty error, return that error with an empty string. | ||
- Otherwise return whatever string `SubTask` returns prepended with the string `"Main task | ||
status:"` and a `nil` error. | ||
|
||
2. `SubTask` should: | ||
- Simulate a long-running task by attempting to run for 200 milliseconds. | ||
- If the provided context is canceled before the task completes, return immediately with the | ||
error provided by the context (use [`ctx.Err()`](https://pkg.go.dev/context#Context)). | ||
- Otherwise, return the string `"Subtask completed successfully"` with an empty error. | ||
|
||
3. Use channels to communicate the subtask result and errors between the goroutines. Make sure to | ||
close the channels in the goroutine that actually writes the channels otherwise you will see | ||
ugly race conditions and random panics. | ||
|
||
4. Ensure proper resource cleanup by using `defer` statements where appropriate. | ||
|
||
Insert the code into the file `exercise.go` at the placeholder `// INSERT YOUR CODE HERE`. | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package subtask | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestStartLongRunningTask(t *testing.T) { | ||
t.Run("Successful completion", func(t *testing.T) { | ||
ctx := context.Background() | ||
result, err := StartTask(ctx) | ||
if err != nil { | ||
t.Errorf("Expected no error, got %v", err) | ||
} | ||
if result != "Main task status: Subtask completed successfully" && | ||
result != "Main task status:Subtask completed successfully" { | ||
t.Errorf("Expected 'Main task status:Subtask completed successfully', got %s", result) | ||
} | ||
}) | ||
|
||
t.Run("Cancelled by main context", func(t *testing.T) { | ||
ctx, cancel := context.WithCancel(context.Background()) | ||
go func() { | ||
time.Sleep(100 * time.Millisecond) | ||
cancel() | ||
}() | ||
|
||
result, err := StartTask(ctx) | ||
if err == nil { | ||
t.Error("Expected an error, got nil") | ||
} | ||
if result != "" { | ||
t.Errorf("Expected empty result, got %s", result) | ||
} | ||
}) | ||
|
||
t.Run("Immediate cancellation", func(t *testing.T) { | ||
ctx, cancel := context.WithCancel(context.Background()) | ||
cancel() // Cancel immediately | ||
|
||
result, err := StartTask(ctx) | ||
if err == nil { | ||
t.Error("Expected an error, got nil") | ||
} | ||
if result != "" { | ||
t.Errorf("Expected empty result, got %s", result) | ||
} | ||
}) | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# PLEASE RUN make generate |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package subtask | ||
|
||
// DO NOT REMOVE THIS COMMENT | ||
//go:generate go run ../../exercises-cli.go -student-id=$STUDENT_ID generate | ||
|
||
// INSERT YOUR CODE HERE |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
name: subtask |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
// PLEASE RUN make generate |