Update network programming season#394
Conversation
WalkthroughDocumentation updates and formatting cleanups across Chapter 5. Minor functional edits include fixing a fatal logging call in the TCP beginner server and switching HTTP client examples from ioutil.ReadAll to io.ReadAll. Additional Persian-language documentation and examples were added to the HTTP server chapter. 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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
content/chapter 5/5.10-quic-server.md (1)
135-147: Weak RSA key size (1024-bit).
Use at least 2048-bit RSA or prefer ECDSA (P-256) for TLS 1.3.- key, err := rsa.GenerateKey(rand.Reader, 1024) + key, err := rsa.GenerateKey(rand.Reader, 2048)Optionally replace with ECDSA (elliptic.P256) to reduce CPU cost.
content/chapter 5/5.3-tcp-server-advanced.md (2)
61-76: Do not use log.Fatal in read loop; fix unbounded buffer growth; check read errors.
- log.Fatal exits the whole process; prefer returning/closing the conn.
- buf is never reset, causing unbounded growth across chunks.
- binary.Read error is ignored.
func (fs *FileServer) readLoop(conn net.Conn) { - // make a new buffer - buf := new(bytes.Buffer) + // a fresh buffer per file + buf := new(bytes.Buffer) for { var size int64 - // get the size from connection - binary.Read(conn, binary.LittleEndian, &size) + // get the size from connection + if err := binary.Read(conn, binary.LittleEndian, &size); err != nil { + log.Printf("size read error: %v", err) + return + } // copy from connection until the end of file n, err := io.CopyN(buf, conn, size) - if err != nil { - log.Fatal(err) - continue - } + if err != nil { + log.Printf("copy error: %v", err) + return + } + // process buf.Bytes() here... + buf.Reset() fmt.Println(buf.Bytes()) fmt.Printf("received %d bytes over the network\n", n) } }
101-112: Close client connection and check write errors.
sendFile leaks the connection and ignores errors from binary.Write.conn, err := net.Dial("tcp", ":3000") if err != nil { return err } +defer conn.Close() // send the size of file - binary.Write(conn, binary.LittleEndian, int64(size)) + if err := binary.Write(conn, binary.LittleEndian, int64(size)); err != nil { + return err + } // copy file over the network until the end of file n, err := io.CopyN(conn, bytes.NewReader(file), int64(size))content/chapter 5/5.9-http-client-advanced.md (1)
216-224: Invalid JSON payload and missing Content-Type in PUT request.Keys/strings must be double-quoted; also set Content-Type to application/json so servers parse it correctly.
-// مقدار های جدید را برای اپدیت شدن وارد میکنیم +// مقدارهای جدید را برای آپدیت وارد میکنیم requestBody := []byte(` - { - title: 'test product', - price: 13.5, - description: 'lorem ipsum set', - image: 'https://i.pravatar.cc', - category: 'electronic' - } +{ + "title": "test product", + "price": 13.5, + "description": "lorem ipsum set", + "image": "https://i.pravatar.cc", + "category": "electronic" +} `) @@ -req, err := http.NewRequest("PUT", url, bytes.NewBuffer(requestBody)) +req, err := http.NewRequest("PUT", url, bytes.NewBuffer(requestBody)) if err != nil { fmt.Println(err) return } +req.Header.Set("Content-Type", "application/json") @@ -// درصورت 200 بودن کد وضعیت اپدیت با موفقیت انجام شده. +// در صورت 200 بودن کد وضعیت، آپدیت با موفقیت انجام شده است. fmt.Println(resp.StatusCode)Also applies to: 226-244
🧹 Nitpick comments (20)
content/chapter 5/5.8-http-client-begginer.md (4)
30-30: Simplify timeout expression.
Use time.Second instead of time.Duration(1) * time.Second.- c := http.Client{Timeout: time.Duration(1) * time.Second} + c := http.Client{Timeout: time.Second}
34-41: Handle non-2xx HTTP responses.
Check resp.StatusCode before reading the body to avoid treating HTTP errors as success.resp, err := c.Get("https://www.example.com") if err != nil { fmt.Printf("Error %s", err) return } defer resp.Body.Close() +if resp.StatusCode < 200 || resp.StatusCode >= 300 { + fmt.Printf("HTTP error: %s\n", resp.Status) + return +}
32-35: Fix Persian typos in comments.
- "درخوایت" → "درخواست"
- Consider adding punctuation and spacing consistency.
-// دقیقا سروری مشابه ... درخوایت ارسال میکنیم ... +// دقیقاً سروری مشابه ... درخواست ارسال میکنیم ...
22-48: Replace hard tabs with spaces in code blocks.
markdownlint (MD010) flags hard tabs across this block. Replace tabs with spaces or configure the linter to ignore fenced code blocks.content/chapter 5/5.10-quic-server.md (5)
64-66: Nit: spelling in comment.
"listner" → "listener".- // make a new listner with quic + // make a new listener with quic
87-94: Nit: comment grammar.
"client function that send the message" → "client function that sends the message".-// client function that send the message to our server +// client function that sends the message to our server
70-85: Accept loops for multiple connections/streams.
Server currently handles a single connection and single stream, then exits. Wrap Accept and AcceptStream in loops for a usable echo server.- // accept incoming connections - conn, err := listener.Accept(context.Background()) - ... - // accept incoming streams - stream, err := conn.AcceptStream(context.Background()) + for { + // accept incoming connections + conn, err := listener.Accept(context.Background()) + if err != nil { return err } + go func(c quic.Connection) { + for { + stream, err := c.AcceptStream(context.Background()) + if err != nil { return } + go func(s quic.Stream) { _, _ = io.Copy(loggingWriter{s}, s) }(stream) + } + }(conn) + }
49-51: Nit: message text consistency.
"hello gifarsi!" vs "gofarsi" elsewhere; pick one for consistency.
1-5: Slug typo.
slug: go-quic-prtoocol → go-quic-protocol. If you change the slug, add an aliases entry to avoid breaking links.slug: go-quic-prtoocol +aliases: ["go-quic-prtoocol"] +slug: go-quic-protocolcontent/chapter 5/5.3-tcp-server-advanced.md (1)
80-85: Handle sendFile error and fix typo.
The goroutine ignores sendFile errors; also "szie" typo.go func() { time.Sleep(4 * time.Second) - // set your file szie - sendFile(2000000) + // set your file size + if err := sendFile(2_000_000); err != nil { + log.Printf("sendFile error: %v", err) + } }()content/chapter 5/5.4-udp-server-begginer.md (2)
14-15: Persian spelling and nuance.
- "تظمین" → "تضمین".
- Consider clarifying that lower overhead often results in lower latency, but “faster than TCP” depends on the application and reliability requirements.
-به همین دلیل سرعت در این پروتکل از پروتکل tcp بیشتر است اما تظمین ارسال کامل و سالم داده وجود ندارد. +به همین دلیل سربار کمتر و معمولاً تأخیر پایینتری نسبت به TCP دارد، اما تضمینی برای ارسال کامل و سالم داده وجود ندارد.
30-55: Replace hard tabs with spaces in code blocks.
markdownlint (MD010) flags hard tabs across this section.content/chapter 5/5.2-tcp-server-begginer.md (2)
92-99: Avoid busy loop on connection read errors.
On read error, continuing the loop can spin on a dead connection. Break or return instead.n, err := conn.Read(buf) if err != nil { - fmt.Println("read error:", err) - continue + fmt.Println("read error:", err) + return }Also consider handling io.EOF distinctly.
98-104: Check write error to the client.
Capture and handle the error from conn.Write to avoid silent failures.- conn.Write([]byte("your message recived!\n")) + if _, err := conn.Write([]byte("your message received!\n")); err != nil { + fmt.Println("write error:", err) + return + }content/chapter 5/5.7-http-server-advanced.md (3)
108-111: Fix Persian typography (ZWNJ) and wording.Apply ZWNJ and minor fixes for clarity.
-پیش از توضیح نحوه تست سرور http ایجاد شده، اجازه بدهید کمی درباره دو مفهوم -کلیدی Encode و Decode که در کد بالا آمده است و ممکن است برای کسانی که تازه وارد بحث -برنامه نویسی شبکه شده اند کمی گنگ باشد، توضیح بدهیم. +پیش از توضیح نحوهٔ تست سرور http ایجادشده، اجازه بدهید کمی دربارهٔ دو مفهوم +کلیدی Encode و Decode که در کد بالا آمده است و ممکن است برای کسانی که تازهواردِ بحث +برنامهنویسی شبکه شدهاند کمی گنگ باشد، توضیح بدهیم.
112-116: Add blank lines after headings (MD022).Headings should be followed by a blank line to satisfy markdownlint.
-## توضیح Encode و Decode در کد -در کدی که نوشتیم، دو عمل خیلی مهم وجود دارد: Encode و Decode. اینها مسئول تبدیل دادهها بین دنیای Go و دنیای JSON هستند. +## توضیح Encode و Decode در کد + +در کدی که نوشتیم، دو عمل خیلی مهم وجود دارد: Encode و Decode. اینها مسئول تبدیل دادهها بین دنیای Go و دنیای JSON هستند. -### Encode -هر وقت بخواهیم دادههای سمت سرور (مثل یک struct یا slice) را به صورت JSON برای کلاینت بفرستیم، از Encode استفاده میکنیم. +### Encode + +هر وقت بخواهیم دادههای سمت سرور (مثل یک struct یا slice) را به صورت JSON برای کلاینت بفرستیم، از Encode استفاده میکنیم. -### Decode -وقتی کلاینت دادهای را به سرور میفرستد (مثلاً با متد POST یا PATCH)، دادهها معمولاً در قالب JSON ارسال میشوند. ما باید این JSON را به یک struct در Go تبدیل کنیم تا بتوانیم راحت با آن کار کنیم. اینجاست که Decode به کار میآید. +### Decode + +وقتی کلاینت دادهای را به سرور میفرستد (مثلاً با متد POST یا PATCH)، دادهها معمولاً در قالب JSON ارسال میشوند. ما باید این JSON را به یک struct در Go تبدیل کنیم تا بتوانیم راحت با آن کار کنیم. اینجاست که Decode به کار میآید.Also applies to: 133-136
120-123: Handle Encode error in the example.Demonstrate best practice by checking the encoder error.
-json.NewEncoder(w).Encode(todos) +if err := json.NewEncoder(w).Encode(todos); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return +}content/chapter 5/5.9-http-client-advanced.md (3)
74-81: Check non-2xx responses before reading body.Small robustness tweak: fail fast on unexpected status codes.
resp, err := http.Get("https://fakestoreapi.com/products") if err != nil { fmt.Println("Error:", err) return } defer resp.Body.Close() -// کد وضعیت پاسخ سرور را چاپ میکنیم -fmt.Println(resp.StatusCode) +// کد وضعیت پاسخ سرور را بررسی/چاپ میکنیم +if resp.StatusCode != http.StatusOK { + fmt.Println("Status:", resp.Status) + return +} +fmt.Println("Status:", resp.Status) // خروجی را در یک اسلایس ذخیره میکنیم body, err := io.ReadAll(resp.Body)Also applies to: 82-93
172-196: Add HTTP client timeout for DELETE request.Prevents hangs on slow/unreachable servers.
-import ( - "fmt" - "net/http" -) +import ( + "fmt" + "net/http" + "time" +) @@ - client := &http.Client{} + client := &http.Client{Timeout: 10 * time.Second}
212-214: Fix typos in Persian comment.Correct wording.
-// ایدی محول مورد نظر را به انتهای url اضافه میکنیم +// شناسهٔ محصول مورد نظر را به انتهای URL اضافه میکنیم
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
content/chapter 5/5.10-quic-server.md(3 hunks)content/chapter 5/5.2-tcp-server-begginer.md(4 hunks)content/chapter 5/5.3-tcp-server-advanced.md(2 hunks)content/chapter 5/5.4-udp-server-begginer.md(4 hunks)content/chapter 5/5.7-http-server-advanced.md(1 hunks)content/chapter 5/5.8-http-client-begginer.md(1 hunks)content/chapter 5/5.9-http-client-advanced.md(4 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
content/chapter 5/5.8-http-client-begginer.md
22-22: Hard tabs
Column: 1
(MD010, no-hard-tabs)
23-23: Hard tabs
Column: 1
(MD010, no-hard-tabs)
24-24: Hard tabs
Column: 1
(MD010, no-hard-tabs)
25-25: Hard tabs
Column: 1
(MD010, no-hard-tabs)
29-29: Hard tabs
Column: 1
(MD010, no-hard-tabs)
30-30: Hard tabs
Column: 1
(MD010, no-hard-tabs)
32-32: Hard tabs
Column: 1
(MD010, no-hard-tabs)
33-33: Hard tabs
Column: 1
(MD010, no-hard-tabs)
34-34: Hard tabs
Column: 1
(MD010, no-hard-tabs)
35-35: Hard tabs
Column: 1
(MD010, no-hard-tabs)
36-36: Hard tabs
Column: 1
(MD010, no-hard-tabs)
37-37: Hard tabs
Column: 1
(MD010, no-hard-tabs)
38-38: Hard tabs
Column: 1
(MD010, no-hard-tabs)
39-39: Hard tabs
Column: 1
(MD010, no-hard-tabs)
40-40: Hard tabs
Column: 1
(MD010, no-hard-tabs)
41-41: Hard tabs
Column: 1
(MD010, no-hard-tabs)
42-42: Hard tabs
Column: 1
(MD010, no-hard-tabs)
43-43: Hard tabs
Column: 1
(MD010, no-hard-tabs)
44-44: Hard tabs
Column: 1
(MD010, no-hard-tabs)
45-45: Hard tabs
Column: 1
(MD010, no-hard-tabs)
46-46: Hard tabs
Column: 1
(MD010, no-hard-tabs)
48-48: Hard tabs
Column: 1
(MD010, no-hard-tabs)
content/chapter 5/5.4-udp-server-begginer.md
30-30: Hard tabs
Column: 1
(MD010, no-hard-tabs)
44-44: Hard tabs
Column: 1
(MD010, no-hard-tabs)
45-45: Hard tabs
Column: 1
(MD010, no-hard-tabs)
46-46: Hard tabs
Column: 1
(MD010, no-hard-tabs)
47-47: Hard tabs
Column: 1
(MD010, no-hard-tabs)
48-48: Hard tabs
Column: 1
(MD010, no-hard-tabs)
49-49: Hard tabs
Column: 1
(MD010, no-hard-tabs)
51-51: Hard tabs
Column: 1
(MD010, no-hard-tabs)
52-52: Hard tabs
Column: 1
(MD010, no-hard-tabs)
53-53: Hard tabs
Column: 1
(MD010, no-hard-tabs)
70-70: Hard tabs
Column: 1
(MD010, no-hard-tabs)
71-71: Hard tabs
Column: 1
(MD010, no-hard-tabs)
73-73: Hard tabs
Column: 1
(MD010, no-hard-tabs)
74-74: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Hard tabs
Column: 1
(MD010, no-hard-tabs)
content/chapter 5/5.7-http-server-advanced.md
112-112: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
115-115: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
120-120: Code block style
Expected: indented; Actual: fenced
(MD046, code-block-style)
126-126: Code block style
Expected: indented; Actual: fenced
(MD046, code-block-style)
133-133: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
138-138: Code block style
Expected: indented; Actual: fenced
(MD046, code-block-style)
144-144: Code block style
Expected: indented; Actual: fenced
(MD046, code-block-style)
content/chapter 5/5.9-http-client-advanced.md
69-69: Hard tabs
Column: 1
(MD010, no-hard-tabs)
70-70: Hard tabs
Column: 1
(MD010, no-hard-tabs)
74-74: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Bare URL used
(MD034, no-bare-urls)
76-76: Hard tabs
Column: 1
(MD010, no-hard-tabs)
77-77: Hard tabs
Column: 1
(MD010, no-hard-tabs)
78-78: Hard tabs
Column: 1
(MD010, no-hard-tabs)
79-79: Hard tabs
Column: 1
(MD010, no-hard-tabs)
80-80: Hard tabs
Column: 1
(MD010, no-hard-tabs)
82-82: Hard tabs
Column: 1
(MD010, no-hard-tabs)
83-83: Hard tabs
Column: 1
(MD010, no-hard-tabs)
85-85: Hard tabs
Column: 1
(MD010, no-hard-tabs)
86-86: 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)
92-92: Hard tabs
Column: 1
(MD010, no-hard-tabs)
93-93: Hard tabs
Column: 1
(MD010, no-hard-tabs)
172-172: Hard tabs
Column: 1
(MD010, no-hard-tabs)
173-173: Hard tabs
Column: 1
(MD010, no-hard-tabs)
177-177: Hard tabs
Column: 1
(MD010, no-hard-tabs)
178-178: Hard tabs
Column: 1
(MD010, no-hard-tabs)
178-178: Bare URL used
(MD034, no-bare-urls)
180-180: Hard tabs
Column: 1
(MD010, no-hard-tabs)
181-181: Hard tabs
Column: 1
(MD010, no-hard-tabs)
182-182: Hard tabs
Column: 1
(MD010, no-hard-tabs)
183-183: Hard tabs
Column: 1
(MD010, no-hard-tabs)
184-184: Hard tabs
Column: 1
(MD010, no-hard-tabs)
186-186: Hard tabs
Column: 1
(MD010, no-hard-tabs)
187-187: Hard tabs
Column: 1
(MD010, no-hard-tabs)
188-188: Hard tabs
Column: 1
(MD010, no-hard-tabs)
189-189: Hard tabs
Column: 1
(MD010, no-hard-tabs)
190-190: Hard tabs
Column: 1
(MD010, no-hard-tabs)
191-191: Hard tabs
Column: 1
(MD010, no-hard-tabs)
192-192: Hard tabs
Column: 1
(MD010, no-hard-tabs)
194-194: Hard tabs
Column: 1
(MD010, no-hard-tabs)
195-195: Hard tabs
Column: 1
(MD010, no-hard-tabs)
212-212: Hard tabs
Column: 1
(MD010, no-hard-tabs)
213-213: Hard tabs
Column: 1
(MD010, no-hard-tabs)
213-213: Bare URL used
(MD034, no-bare-urls)
215-215: Hard tabs
Column: 1
(MD010, no-hard-tabs)
216-216: Hard tabs
Column: 1
(MD010, no-hard-tabs)
226-226: Hard tabs
Column: 1
(MD010, no-hard-tabs)
227-227: Hard tabs
Column: 1
(MD010, no-hard-tabs)
228-228: Hard tabs
Column: 1
(MD010, no-hard-tabs)
229-229: Hard tabs
Column: 1
(MD010, no-hard-tabs)
230-230: Hard tabs
Column: 1
(MD010, no-hard-tabs)
231-231: Hard tabs
Column: 1
(MD010, no-hard-tabs)
233-233: Hard tabs
Column: 1
(MD010, no-hard-tabs)
234-234: Hard tabs
Column: 1
(MD010, no-hard-tabs)
235-235: Hard tabs
Column: 1
(MD010, no-hard-tabs)
236-236: Hard tabs
Column: 1
(MD010, no-hard-tabs)
237-237: Hard tabs
Column: 1
(MD010, no-hard-tabs)
238-238: Hard tabs
Column: 1
(MD010, no-hard-tabs)
239-239: Hard tabs
Column: 1
(MD010, no-hard-tabs)
240-240: Hard tabs
Column: 1
(MD010, no-hard-tabs)
242-242: Hard tabs
Column: 1
(MD010, no-hard-tabs)
243-243: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🪛 LanguageTool
content/chapter 5/5.7-http-server-advanced.md
[whitespace] ~109-~109: آیا منظور شما «"تازهوارد"» است؟
Context: ... بالا آمده است و ممکن است برای کسانی که تازه وارد بحث برنامه نویسی شبکه شده اند کمی گنگ ب...
(ZWNJ_Connection)
🔇 Additional comments (5)
content/chapter 5/5.8-http-client-begginer.md (2)
22-25: Good migration to io.ReadAll and tidy imports.
The switch from io/ioutil to io is correct and future-proof.
42-47: Nice: added read error handling.
The explicit check around io.ReadAll is a solid improvement.content/chapter 5/5.3-tcp-server-advanced.md (1)
34-34: LGTM: idiomatic empty struct.
type FileServer struct{} is the idiomatic form.content/chapter 5/5.2-tcp-server-begginer.md (1)
116-117: Correct fix: log.Fatal instead of log.Fetal.
Good catch; this prevents a runtime panic due to an undefined identifier and ensures proper fatal logging.content/chapter 5/5.9-http-client-advanced.md (1)
69-71: Good update: migrate to io.ReadAll.Moving from ioutil.ReadAll to io.ReadAll is correct and modern.
| tlsConf := &tls.Config{ | ||
| InsecureSkipVerify: true, | ||
| NextProtos: []string{"quic-echo-example"}, | ||
| } | ||
| // dial with our udp server | ||
|
|
||
| // dial with our udp server | ||
| conn, err := quic.DialAddr(context.Background(), addr, tlsConf, nil) | ||
| if err != nil { |
There was a problem hiding this comment.
Insecure TLS on client (InsecureSkipVerify).
InsecureSkipVerify: true disables certificate verification. For an example with a self-signed cert, trust the server cert via a cert pool instead.
- tlsConf := &tls.Config{
- InsecureSkipVerify: true,
- NextProtos: []string{"quic-echo-example"},
- }
+ certPool := x509.NewCertPool()
+ // TODO: add server cert to pool (e.g., from generateTLSConfig output)
+ tlsConf := &tls.Config{
+ RootCAs: certPool,
+ NextProtos: []string{"quic-echo-example"},
+ }If keeping it as a quick demo, add a prominent warning in the text.
📝 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.
| tlsConf := &tls.Config{ | |
| InsecureSkipVerify: true, | |
| NextProtos: []string{"quic-echo-example"}, | |
| } | |
| // dial with our udp server | |
| // dial with our udp server | |
| conn, err := quic.DialAddr(context.Background(), addr, tlsConf, nil) | |
| if err != nil { | |
| // …earlier code… | |
| // Trust only our self-signed server certificate instead of skipping verification. | |
| certPool := x509.NewCertPool() | |
| // TODO: load and add the server’s certificate to certPool, e.g.: | |
| // certData, _ := os.ReadFile("server-cert.pem") | |
| // certPool.AppendCertsFromPEM(certData) | |
| tlsConf := &tls.Config{ | |
| RootCAs: certPool, | |
| NextProtos: []string{"quic-echo-example"}, | |
| } | |
| // dial with our udp server | |
| conn, err := quic.DialAddr(context.Background(), addr, tlsConf, nil) | |
| if err != nil { | |
| // … | |
| } | |
| // …remaining code… |
🤖 Prompt for AI Agents
In content/chapter 5/5.10-quic-server.md around lines 90 to 97, the client TLS
config uses InsecureSkipVerify: true which disables certificate verification;
replace this by loading the server's certificate into a x509.CertPool and set
tls.Config.RootCAs (and optionally ServerName) so the client trusts the
self-signed cert, or if you must keep the insecure setting for a short demo add
a prominent warning in the text above the code block stating that
InsecureSkipVerify disables certificate verification and must never be used in
production.
| // یک اتصال به سرور ایجاد میکنیم | ||
| Conn, _ := net.DialUDP("udp", nil, &net.UDPAddr{IP: []byte{127, 0, 0, 1}, Port: 3000, Zone: ""}) | ||
|
|
||
| defer Conn.Close() | ||
| // متن زیر را به سرور ارسال میکنیم | ||
| Conn.Write([]byte("hello, gofarsi!")) | ||
| defer Conn.Close() | ||
| // متن زیر را به سرور ارسال میکنیم | ||
| Conn.Write([]byte("hello, gofarsi!")) | ||
| } |
There was a problem hiding this comment.
Invalid UDPAddr IP literal; missing error handling.
IP field expects net.IP; []byte literal won’t assign to net.IP without conversion. Also don’t discard the error from net.DialUDP.
- // یک اتصال به سرور ایجاد میکنیم
- Conn, _ := net.DialUDP("udp", nil, &net.UDPAddr{IP: []byte{127, 0, 0, 1}, Port: 3000, Zone: ""})
+ // یک اتصال به سرور ایجاد میکنیم
+ conn, err := net.DialUDP("udp", nil, &net.UDPAddr{
+ IP: net.ParseIP("127.0.0.1"),
+ Port: 3000,
+ })
+ if err != nil {
+ panic(err)
+ }
- defer Conn.Close()
+ defer conn.Close()
- // متن زیر را به سرور ارسال میکنیم
- Conn.Write([]byte("hello, gofarsi!"))
+ // متن زیر را به سرور ارسال میکنیم
+ if _, err := conn.Write([]byte("hello, gofarsi!")); err != nil {
+ panic(err)
+ }Also rename Conn → conn to follow Go naming conventions.
📝 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.
| // یک اتصال به سرور ایجاد میکنیم | |
| Conn, _ := net.DialUDP("udp", nil, &net.UDPAddr{IP: []byte{127, 0, 0, 1}, Port: 3000, Zone: ""}) | |
| defer Conn.Close() | |
| // متن زیر را به سرور ارسال میکنیم | |
| Conn.Write([]byte("hello, gofarsi!")) | |
| defer Conn.Close() | |
| // متن زیر را به سرور ارسال میکنیم | |
| Conn.Write([]byte("hello, gofarsi!")) | |
| } | |
| // یک اتصال به سرور ایجاد میکنیم | |
| conn, err := net.DialUDP("udp", nil, &net.UDPAddr{ | |
| IP: net.ParseIP("127.0.0.1"), | |
| Port: 3000, | |
| }) | |
| if err != nil { | |
| panic(err) | |
| } | |
| defer conn.Close() | |
| // متن زیر را به سرور ارسال میکنیم | |
| if _, err := conn.Write([]byte("hello, gofarsi!")); err != nil { | |
| panic(err) | |
| } | |
| } |
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
70-70: Hard tabs
Column: 1
(MD010, no-hard-tabs)
71-71: Hard tabs
Column: 1
(MD010, no-hard-tabs)
73-73: Hard tabs
Column: 1
(MD010, no-hard-tabs)
74-74: Hard tabs
Column: 1
(MD010, no-hard-tabs)
75-75: Hard tabs
Column: 1
(MD010, no-hard-tabs)
🤖 Prompt for AI Agents
In content/chapter 5/5.4-udp-server-begginer.md around lines 70 to 76, the UDP
client code uses a []byte literal for UDPAddr.IP, ignores the error returned by
net.DialUDP, and uses a capitalized Conn identifier; change the IP to a net.IP
(e.g. net.IPv4(127,0,0,1) or net.ParseIP("127.0.0.1")), capture and handle the
(conn, err) returned by net.DialUDP (return or log and exit on error), rename
Conn to conn (lowercase) and defer conn.Close(), and also check the error
returned by conn.Write and handle it.
| json.NewDecoder(r.Body).Decode(&todo) | ||
| ``` | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Validate request body on Decode.
Show decoding error handling to avoid 200 on malformed JSON.
-json.NewDecoder(r.Body).Decode(&todo)
+if err := json.NewDecoder(r.Body).Decode(&todo); err != nil {
+ http.Error(w, "invalid JSON", http.StatusBadRequest)
+ return
+}📝 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.
| json.NewDecoder(r.Body).Decode(&todo) | |
| ``` | |
| if err := json.NewDecoder(r.Body).Decode(&todo); err != nil { | |
| http.Error(w, "invalid JSON", http.StatusBadRequest) | |
| return | |
| } |
🤖 Prompt for AI Agents
In content/chapter 5/5.7-http-server-advanced.md around lines 139–141, the call
json.NewDecoder(r.Body).Decode(&todo) ignores the returned error so malformed
JSON will still return 200; capture and check the error from Decode and return a
400 Bad Request (e.g., via http.Error or w.WriteHeader with a JSON error body)
when decoding fails, optionally validating the decoded struct and
closing/limiting the request body (e.g., via r.Body = http.MaxBytesReader)
before decoding to prevent oversized payloads.
5.2 => Fix typo error, log.Fetal used instead of log.Fatal
5.3 => Remove additional enters for better code format
5.4.1 => Fix incorrect UDP vs TCP speed description
5.4.2 => Remove additional enters for better code format
5.4.3 => Modify code format
5.7 => Add explanation about encode and decode in code
5.8 => Use io instead of io/ioutil which is deprecated and write an error check
5.9.3 => Use io instead of io/ioutil which is deprecated
5.9.5 => Add some enters for better code format
5.9.6 => Fix code format error and modify it
5.10 => Modify code format
Summary by CodeRabbit
New Features
Documentation
Bug Fixes