ใน Part 4 นี้จะเป็นเรื่องที่ลึกไปอีกขั้น แต่ยังเป็นสำหรับมือใหม่อยู่ !!
ประกอบไปด้วย
- การใช้งาน channel
- การใช้งาน struct
- การใช้งาน net/http package
- การใช้งาน encoding/json package
มาเริ่มกันเลย
เรื่องที่ 31 การส่งข้อมูลไปยัง channel ที่ปิดไปแล้ว ทำให้เกิด panic
ตัวอย่าง code ที่ทำการส่งข้อมูลไปยัง channel ที่ปิดไปแล้ว จะเกิด panic ขึ้นมา
ทำให้ program หยุดการทำงานทันที (ถ้าจัดการ panic ไม่ดี)
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="31.go"]
การแก้ไขปัญหานี้มีหลายวิธีการ ขึ้นอยู่กับระบบหรือความต้องการไป
เพื่อทำให้มั่นใจว่า จะไม่ส่งข้อมูลไปยัง channel ที่ปิดแล้ว
ยกตัวอย่างเช่น
ทำการสร้าง channel ใหม่ขึ้นมา เพื่อใช้สำหรับการยกเลิกการทำงาน
หรือ บอกว่าทำการปิด channel แล้ว
จากนั้นจะทำการส่งสัญญาณไปบอกให้ worker ต่าง ๆ รู้นั่นเอง
จากตัวอย่าง code ข้างล่าง จะสร้าง channel ชื่อว่า done ขึ้นมา
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="312.go"]
เรื่องที่ 32 การใช้งาน channel ที่เป็น nil ก่อให้เกิด deadlock ขึ้นมา
ในการใช้งาน channel นั้น ถ้านักพัฒนาเพียงประกาศ channel ที่เป็น nil ขึ้นมาแล้ว
จะก่อให้เกิดปัญหาขึ้นมา นั่นคือ channel จะโดน block ไว้
ดังนั้นงานอื่น ๆ จะไม่สามารถทำงานได้
มันคือ deadlock ดี ๆ นี่เอง ซึ่งต้องระวังให้มาก ๆ
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="32.go"]
เรื่องที่ 33 Methods with Value Receivers Can't Change the Original Value
Method receiver นั้นจะเหมือนกับ argument ของ function นั่นคือ
ถ้าทำการประกาศแบบปกติ จะเป็นการ pass by value (เป็นค่าของข้อมูล ไม่ใช่ตำแหน่ง) ทำให้เมื่อทำการแก้ไขข้อมูลแล้ว จะไม่กระทบกับข้อมูลต้นทางหรือ original
ดัง code ตัวอย่าง
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="33.go"]
ดังนั้นถ้าต้องการให้การแก้ไขข้อมูลใน method มีผลต่อต้นทางด้วย
การส่งค่าหรือ value เป็นตำแหน่งแทนด้วย pointer ดังนี้
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="332.go"]
เรื่องที่ 34 Closing HTTP Connections
ว่าด้วยเรื่องของการปิด HTTP connection
โดยปกติเมื่อทำการ start HTTP server แล้ว
Connection หรือช่องทางการติดต่อจะถูกสร้างและเปิดขึ้นมา
จะเปิดค้างไว้ หรือ ปิดไปเมื่อใช้งานเสร็จ ก็ขึ้นอยู่กับงานของเรา
จากเอกสารของ HTTP 1.1 นั้นสามารถกำหนดค่าผ่าน keep-alive ใน HTTP Header
จาก package net/http ในภาษา Go นั้น
จะทำการปิด connection เมื่อ HTTP server บอกให้ปิดเท่านั้น (จะปิดตอนไหนละ ?)
ซึ่งอาจจะส่งผลทำให้เกิดปัญหาคือ
เปิด socket/file descriptor มากเกินที่มีให้
ดังนั้นการแก้ไขมีหลายแบบ ขึ้นอยู่กับความต้องการของระบบงาน
ทั้งเพิ่มจำนวน socket ที่เปิดได้
ทั้งเพิ่มจำนวน file descriptor
ทั้งการปิด connection เมื่อใช้งานเสร็จแล้ว
โดยการเพื่อค่า Connection = Close ใน HTTP Header หรือกำหนด property Close ใน request เป็น true ดังนี้
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="34.go"]
หรือถ้าไม่ต้องการให้ใช้ HTTP connection ร่วมกัน
ก็สามารถปิดได้ ด้วยการ custom HTTP transportation กันไปเลย
กำหนดค่า DisableKeepAlives = true ไป ดังนี้
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="342.go"]
แต่ถ้ามีการส่ง request มายัง HTTP server เดียวกันจำนวนมากแล้ว
ควรต้องให้มีการใช้ HTTP connection ร่วมกัน หรือ เปิด connection ทิ้งไว้
เพราะว่าการสร้าง connection ถือว่าต้องใช้ resource เยอะ
แต่ถ้าจำนวน request ไม่เยอะ ก็ให้เปิดและปิดไป น่าจะเหมาะสมกว่า
ดังนั้น วิธีการมันขึ้นอยู่กับงานกันมากกว่า
เรื่องที่ 35 Closing HTTP Response Body
เมื่อผ่านเรื่องของ การปิด HTTP Connection มาแล้ว
ก็มาถึงการปิด HTTP Reponse ที่ได้รับกลับมา
จากการส่ง request ไปยัง server ปลายทางกันบ้าง
ปัญหาที่มักจะเกิดขึ้นสำหรับนักพัฒนา Go คือ
ถ้าไม่สามารถอ่านข้อมูลจาก body ใน response แล้ว
ต้องการที่จะปิดมันซะ ส่วนใหญ่จะทำการปิดใน defer ตามตำรา
ดังนี้ ซึ่งจะทำได้ดีถ้าได้รับ response แบบปกติหรือสำเร็จกลับมา
แต่ถ้าเกิดมีปัญหาขึ้นมา สิ่งที่ต้องเจอคือ panic นั่นเอง
เพราะว่า reponse จะมีค่าเป็น nil
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="35.go"]
การแก้ไขปัญหาก็ไม่ยากคือ ตรวจสอบก่อนทำการปิดว่า response มีค่าเป็น nil หรือไม่ ? ถ้าไม่ nil ก็ close ได้ ดังนี้
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="352.go"]
เรื่องที่ 36 JSON Encoder Adds a Newline Character
เมื่อทำการแปลงข้อมูลจาก object ต่าง ๆ มาอยู่ในรูปแบบ JSON
ด้วย JSON Encoder จาก encoding/json package แล้ว
จะพบว่าสิ่งที่ได้เพิ่มขึ้นมาคือ newline chareacter (\n)
ทำให้ในการทดสอบอาจจะผิดพลาดขึ้นมาได้
เนื่องจาก JSON Encoder จาก encoding/json package นั้น
ออกแบบมาสำหรับ streaming การเพิ่ม newline character ขึ้นมา
เพื่อใช้แยก JSON object แต่ละตัวออกจากกันนั่นเอง
เรื่องเล็ก ๆ แบบนี้นักพัฒนาอาจจะหลงลืมไป
ทั้ง ๆ ที่ในเอกสารหรือใน code ก็เขียนไว้อย่างชัดเจน
ไปดู code ของ JSON Encoder ดูนะ
[gist id="ea56fa327f9acbad9e479e49cf428c53" file="36.go"]