Update generics season#395
Conversation
WalkthroughDocumentation updates convert multiple Go examples in chapter 6 to interactive playground embeds and runnable demos. Minor formatting adjustments occur in interface declarations. One bug fix updates a method call (Int → Int()) in a non-generic Max example. No public API signatures are changed. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
✨ Finishing Touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
content/chapter 6/6.2-generics fundamentals.md (1)
13-17: Fix author name and unify “ژنریک” spelling.Correct “Ian Lance Taylor” and keep “ژنریک” consistent across the page.
-**یه جمله ای از Ian lancer tailor هست:** +**نقلقولی از Ian Lance Taylor:** -زمانی باید از جنریک استفاده کرد که کد شما بواسطه تغییر تایپ تکرار می شود یا اینکه برای کاهش assertion از جنریک استفاده کنیم. +زمانی باید از ژنریک استفاده کرد که کد شما بهواسطه تغییر نوع تکراری میشود یا برای کاهش type assertion از ژنریک استفاده میکنید.
🧹 Nitpick comments (9)
content/chapter 6/6.5-generics examples and practical.md (3)
193-215: Rename variables to match the data structure (Queue).Variables are named Stack in a Queue example; rename for clarity.
- stringStack := Queue[string]{ + stringQueue := Queue[string]{ data: []string{"test1", "test2", "test3"}, } - fmt.Println(stringStack) - stringStack.Enqueue("test4") - stringStack.Enqueue("test5") - fmt.Println(stringStack) - stringStack.Dequeue() - fmt.Println(stringStack) + fmt.Println(stringQueue) + stringQueue.Enqueue("test4") + stringQueue.Enqueue("test5") + fmt.Println(stringQueue) + stringQueue.Dequeue() + fmt.Println(stringQueue) - intStack := Queue[int]{ + intQueue := Queue[int]{ data: []int{1, 2, 3}, } - fmt.Println(intStack) - intStack.Enqueue(4) - intStack.Enqueue(5) - fmt.Println(intStack) - intStack.Dequeue() - fmt.Println(intStack) + fmt.Println(intQueue) + intQueue.Enqueue(4) + intQueue.Enqueue(5) + fmt.Println(intQueue) + intQueue.Dequeue() + fmt.Println(intQueue)
87-106: Use a clearer predicate name.“prediction” misleads; prefer a predicate-style name.
- res := Filter(testSlice, prediction) + res := Filter(testSlice, isTestTask) ... -func prediction(str string) bool { +func isTestTask(str string) bool { return strings.Contains(str, "test") }
317-337: Missing import for errors in the repo example (if made runnable).The snippet uses errors.New but doesn’t import errors. If you convert this to a {{< play >}} block later, add the import.
content/chapter 6/6.6-comparing generics with solutions before Go 1.18.md (1)
14-21: Clean up extra blank lines flagged by markdownlint.Resolve MD012 (no-multiple-blanks) around the playground fence and after main for a cleaner diff and passing lint.
Also applies to: 36-41
content/chapter 6/6.3-generics syntax and structure.md (1)
102-106: Fix typos: “orginal” → “original”.Minor text polish in demo output.
- fmt.Println("orginal int stack: ", intStack.items) + fmt.Println("original int stack: ", intStack.items) ... - fmt.Println("orginal string stack: ", stringStack.items) + fmt.Println("original string stack: ", stringStack.items)Also applies to: 115-121
content/chapter 6/6.2-generics fundamentals.md (2)
85-90: Prefer fmt.Println over the built-in print for consistency/output stream.Use fmt for labeled output alongside fmt.Println in Print.
- print("string slice: ") + fmt.Println("string slice:") ... - print("int slice: ") + fmt.Println("int slice:")
27-50: Address markdownlint warnings (MD010/MD046).Tabs inside code blocks and an indented code block were flagged. Either replace tabs with spaces in code blocks or configure markdownlint to ignore fenced/shortcode code sections; also convert any indented blocks to fenced.
Also applies to: 72-92, 100-117
content/chapter 6/6.4-generics type sets and constraints.md (2)
26-29: Nit: make output labels consistentAdd a colon to the second println to match the first one’s label.
- fmt.Println("float sum", Sum(2.2, 3.4)) + fmt.Println("float sum:", Sum(2.2, 3.4))
68-74: Prefer using the standard fmt.Stringer instead of redefining StringerLeverage the built-in interface to avoid duplication and align with Go conventions.
-type Stringer interface { - String() string -} - -func PrintString[T Stringer](v T) { +func PrintString[T fmt.Stringer](v T) { fmt.Println(v.String()) }Optionally, you could rely on formatting to call String implicitly:
func PrintString[T fmt.Stringer](v T) { fmt.Println(v) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
content/chapter 6/6.2-generics fundamentals.md(3 hunks)content/chapter 6/6.3-generics syntax and structure.md(1 hunks)content/chapter 6/6.4-generics type sets and constraints.md(3 hunks)content/chapter 6/6.5-generics examples and practical.md(3 hunks)content/chapter 6/6.6-comparing generics with solutions before Go 1.18.md(1 hunks)content/chapter 6/6.7-limitations, errors, and anti-patterns in generics.md(1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
content/chapter 6/6.6-comparing generics with solutions before Go 1.18.md
28-28: Multiple consecutive blank lines
Expected: 1; Actual: 2
(MD012, no-multiple-blanks)
37-37: Multiple consecutive blank lines
Expected: 1; Actual: 2
(MD012, no-multiple-blanks)
content/chapter 6/6.2-generics fundamentals.md
33-33: Multiple consecutive blank lines
Expected: 1; Actual: 2
(MD012, no-multiple-blanks)
47-47: Multiple consecutive blank lines
Expected: 1; Actual: 2
(MD012, no-multiple-blanks)
79-79: Hard tabs
Column: 1
(MD010, no-hard-tabs)
83-83: Hard tabs
Column: 1
(MD010, no-hard-tabs)
87-87: Hard tabs
Column: 1
(MD010, no-hard-tabs)
88-88: Hard tabs
Column: 1
(MD010, no-hard-tabs)
89-89: Hard tabs
Column: 1
(MD010, no-hard-tabs)
90-90: Hard tabs
Column: 1
(MD010, no-hard-tabs)
91-91: Hard tabs
Column: 1
(MD010, no-hard-tabs)
100-100: Hard tabs
Column: 1
(MD010, no-hard-tabs)
102-102: Hard tabs
Column: 1
(MD010, no-hard-tabs)
102-102: Code block style
Expected: fenced; Actual: indented
(MD046, code-block-style)
103-103: Hard tabs
Column: 1
(MD010, no-hard-tabs)
104-104: Hard tabs
Column: 1
(MD010, no-hard-tabs)
105-105: Hard tabs
Column: 1
(MD010, no-hard-tabs)
106-106: Hard tabs
Column: 1
(MD010, no-hard-tabs)
107-107: Hard tabs
Column: 1
(MD010, no-hard-tabs)
109-109: Hard tabs
Column: 1
(MD010, no-hard-tabs)
111-111: Hard tabs
Column: 1
(MD010, no-hard-tabs)
112-112: Hard tabs
Column: 1
(MD010, no-hard-tabs)
113-113: Hard tabs
Column: 1
(MD010, no-hard-tabs)
115-115: Hard tabs
Column: 1
(MD010, no-hard-tabs)
116-116: Hard tabs
Column: 1
(MD010, no-hard-tabs)
117-117: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🔇 Additional comments (5)
content/chapter 6/6.7-limitations, errors, and anti-patterns in generics.md (1)
124-127: Resolved: Verified Go 1.24/1.25 features Generic type aliases were added in Go 1.24 and the core types notion was removed in Go 1.25 per the official release notes (tip.golang.org)content/chapter 6/6.6-comparing generics with solutions before Go 1.18.md (1)
26-33: LGTM: Correct fix using bv.Int().The reflect-based comparison now correctly calls Int() on reflect.Value.
content/chapter 6/6.4-generics type sets and constraints.md (3)
81-99: LGTM: clear Numeric constraint and Max implementationExample compiles and demonstrates union type-set constraints well.
135-154: LGTM: idiomatic Contains with comparableStraightforward and correct; good use of comparable.
160-178: LGTM: Ordered example with cmp is correctAccurate use of cmp.Ordered and a minimal Min implementation.
| strGet, ok := stringStack.Get(1) | ||
| if !ok { | ||
| log.Println("not find") | ||
| } | ||
| fmt.Println("founded: ", strGet) | ||
|
|
||
| fmt.Println() | ||
|
|
||
| intStack := List[int]{ | ||
| items: []int{1, 2, 3}, | ||
| } | ||
| fmt.Println(intStack) | ||
| intStack.Add(4) | ||
| intStack.Add(5) | ||
| fmt.Println(intStack) | ||
| intGet, ok := intStack.Get(1) | ||
| if !ok { | ||
| log.Println("not find") | ||
| } | ||
| fmt.Println("founded: ", intGet) | ||
| } |
There was a problem hiding this comment.
Fix user-facing messages (“not found”, “found”).
Minor English fixes in logs/prints.
- if !ok {
- log.Println("not find")
- }
- fmt.Println("founded: ", strGet)
+ if !ok {
+ log.Println("not found")
+ }
+ fmt.Println("found: ", strGet)
...
- if !ok {
- log.Println("not find")
- }
- fmt.Println("founded: ", intGet)
+ if !ok {
+ log.Println("not found")
+ }
+ fmt.Println("found: ", intGet)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| strGet, ok := stringStack.Get(1) | |
| if !ok { | |
| log.Println("not find") | |
| } | |
| fmt.Println("founded: ", strGet) | |
| fmt.Println() | |
| intStack := List[int]{ | |
| items: []int{1, 2, 3}, | |
| } | |
| fmt.Println(intStack) | |
| intStack.Add(4) | |
| intStack.Add(5) | |
| fmt.Println(intStack) | |
| intGet, ok := intStack.Get(1) | |
| if !ok { | |
| log.Println("not find") | |
| } | |
| fmt.Println("founded: ", intGet) | |
| } | |
| strGet, ok := stringStack.Get(1) | |
| if !ok { | |
| log.Println("not found") | |
| } | |
| fmt.Println("found: ", strGet) | |
| fmt.Println() | |
| intStack := List[int]{ | |
| items: []int{1, 2, 3}, | |
| } | |
| fmt.Println(intStack) | |
| intStack.Add(4) | |
| intStack.Add(5) | |
| fmt.Println(intStack) | |
| intGet, ok := intStack.Get(1) | |
| if !ok { | |
| log.Println("not found") | |
| } | |
| fmt.Println("found: ", intGet) | |
| } |
🤖 Prompt for AI Agents
In content/chapter 6/6.5-generics examples and practical.md around lines 255 to
275, update the user-facing messages for correctness: replace log.Println("not
find") with log.Println("not found") (both occurrences) and change
fmt.Println("founded: ", ...) to fmt.Println("found:", ...) to use proper
English and consistent punctuation/capitalization.
| package main | ||
|
|
||
| import "fmt" | ||
|
|
||
| func PrintMapKeys[K comparable, V any](m map[K]V) { | ||
| for k := range m { | ||
| fmt.Println(k) | ||
| } | ||
| for k := range m { | ||
| fmt.Println(k) | ||
| } | ||
| } | ||
|
|
||
| PrintMapKeys(map[[]int]int{}) // error: []int does not implement comparable | ||
| func main() { | ||
| PrintMapKeys(map[[]int]int{}) // error: []int does not implement comparable | ||
|
|
||
| // use this instead: | ||
| // testMap := make(map[string]int) | ||
| // PrintMapKeys(testMap) | ||
| } | ||
| ``` |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Make the error demo compile while still illustrating the issue.
The current main triggers a compile-time error and isn’t runnable. Keep the invalid call as a commented line with the expected error, and enable the valid example so the snippet runs.
func main() {
- PrintMapKeys(map[[]int]int{}) // error: []int does not implement comparable
+ // Compile-time error example (intentionally invalid):
+ // PrintMapKeys(map[[]int]int{}) // []int does not implement comparable
+
+ // Use this instead:
+ testMap := make(map[string]int)
+ PrintMapKeys(testMap)
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| package main | |
| import "fmt" | |
| func PrintMapKeys[K comparable, V any](m map[K]V) { | |
| for k := range m { | |
| fmt.Println(k) | |
| } | |
| for k := range m { | |
| fmt.Println(k) | |
| } | |
| } | |
| PrintMapKeys(map[[]int]int{}) // error: []int does not implement comparable | |
| func main() { | |
| PrintMapKeys(map[[]int]int{}) // error: []int does not implement comparable | |
| // use this instead: | |
| // testMap := make(map[string]int) | |
| // PrintMapKeys(testMap) | |
| } | |
| ``` | |
| package main | |
| import "fmt" | |
| func PrintMapKeys[K comparable, V any](m map[K]V) { | |
| for k := range m { | |
| fmt.Println(k) | |
| } | |
| } | |
| func main() { | |
| // Compile-time error example (intentionally invalid): | |
| // PrintMapKeys(map[[]int]int{}) // []int does not implement comparable | |
| // Use this instead: | |
| testMap := make(map[string]int) | |
| PrintMapKeys(testMap) | |
| } |
🤖 Prompt for AI Agents
In content/chapter 6/6.7-limitations, errors, and anti-patterns in generics.md
around lines 62 to 79, the main function currently contains an actual invalid
call PrintMapKeys(map[[]int]int{}) which causes a compile-time error; comment
out that invalid call and keep a brief comment showing the expected error, then
enable the valid example by creating a concrete map (e.g., testMap :=
make(map[string]int) or a literal) and calling PrintMapKeys(testMap) so the
snippet compiles and still demonstrates the limitation.
6.2.1 => Make the code executable
6.2.2.1 => Make the code executable
6.2.2.2 => Make the code executable
6.3.2 => Make stack example executable
6.4.1 => Make the code executable
6.4.2.1 => Make the code executable
6.4.2.2 => Make the code executable
6.4.3 => Make the comparable example executable
6.4.3 => Make the ordered example executable
6.5.1.1 => Make the code executable
6.5.1.2 => Make the code executable
6.5.1.3 => Make the code executable
6.5.2.1 => Make the code executable
6.5.2.2 => Make the code executable
6.5.2.3 => Make the code executable
6.6.1 => Fix package not found error
6.7.2 => Explain correct situation too
Summary by CodeRabbit