Mastering Golang for E-commerce Back End Development : Part 1
บทความโดย ผศ.ดร.ณัฐโชติ พรหมฤทธิ์ และ อ.ดร.สัจจาภรณ์ ไวจรรยา
ภาควิชาคอมพิวเตอร์
คณะวิทยาศาสตร์
มหาวิทยาลัยศิลปากร
ในยุคดิจิทัลที่การค้า Online เติบโตอย่างก้าวกระโดด การพัฒนาระบบ E-commerce ที่มีประสิทธิภาพ รวดเร็ว และรองรับผู้ใช้จำนวนมาก ได้กลายเป็นความท้าทายสำหรับนักพัฒนา
Go หรือ Golang ได้ก้าวขึ้นมาเป็นหนึ่งใน Programming Language ที่ได้รับความนิยมอย่างสูงในการพัฒนาระบบ Back End ที่หลายบริษัทเลือกใช้ อย่างเช่น Uber, Cloudflare และ Dropbox
ในบทความนี้ซึ่งมีทั้งหมด 4 Part เราจะเรียนรู้แนวคิด เทคนิค และวิธีการใช้ Go เพื่อสร้างระบบ Back End ที่มีประสิทธิภาพ ปลอดภัย และขยายขนาดได้
ไม่ว่าคุณจะเป็น Developer มือใหม่ หรือมีประสบการณ์ บทความนี้จะช่วยให้คุณสามารถใช้ประโยชน์จากพลังของ Go ในการพัฒนา E-commerce Platform ได้อย่างเต็มประสิทธิภาพ โดยจะมีเนื้อหาทั้งหมด 19 หัวข้อ ดังต่อไปนี้
- รู้จักภาษา Go
เป็นจุดเริ่มต้นที่ให้ภาพรวมของภาษาและเหตุผลในการเลือกใช้ Go - ABC ของ Go
สอนพื้นฐานการเขียน Code เช่น ตัวแปร ชนิดข้อมูล การพิมพ์ข้อความ ซึ่งจำเป็นในการเขียน Code ในทุกหัวข้อถัดไป - การตัดสินใจใน Code
แนะนำโครงสร้างการควบคุม เช่น if, else, loop ต่อยอดจากพื้นฐาน เพิ่มความสามารถในการควบคุมการทำงานของ Program - Function : วิธีทำสิ่งต่าง ๆ ที่ใช้ซ้ำได้
สอนการสร้าง และใช้งาน Function ซึ่งเป็นพื้นฐานสำคัญสำหรับการจัดการ Code ที่ซับซ้อน และการนำไปใช้กับโครงสร้างข้อมูลในหัวข้อต่อไป - Array, Slice และ Map : กล่องเก็บของเล่นที่มีช่องหลายช่อง
แนะนำโครงสร้างข้อมูล Array, Slice และ Map โดยใช้ความรู้จากหัวข้อก่อนหน้าในการจัดการข้อมูลจำนวนมาก - Pointer : ส่งรีโมทให้คนอื่นใช้ ง่ายกว่าการยกทีวีทั้งเครื่องไปให้
อธิบายแนวคิดของ Pointer และการใช้งาน ซึ่งจำเป็นสำหรับการทำงานภายในของ Go และการจัดการหน่วยความจำ - Struct และ Method : สร้างสิ่งของของเราเอง
แนะนำการสร้างและใช้งาน Struct และ Method โดยใช้ความรู้ก่อนหน้าในการสร้างโครงสร้างข้อมูลที่ซับซ้อนขึ้น - Interface : ทำความรู้จักกับเพื่อนใหม่
อธิบายแนวคิดและการใช้งาน Interface ต่อยอด Struct และ Method เพื่อสร้างความยืดหยุ่นในการเขียน Code - Package และ Module : แต่ละแผนกมีหน้าที่เฉพาะ และโครงการใหญ่ที่ประกอบด้วยหลายแผนก
แนะนำการจัดการ Code เป็น Package และการใช้ Module ในการจัดระเบียบ Code ขนาดใหญ่ - Errors, Defer, Panic และ Recover : จัดการกับปัญหา
สอนการจัดการ Error, Defer, Panic และ Recover ต่อยอดความรู้ในการเขียน Program ที่แข็งแกร่งและการจัดการข้อผิดพลาด - การทดสอบเบื้องต้น : ลองชิมอาหารก่อนเสิร์ฟ
สอนการเขียน Unit Test และใช้ go test ในการทดสอบ Code ที่เขียนขึ้น - ทำงานกับ File และข้อมูล
สอนการอ่านเขียน File และจัดการข้อมูล JSON - ทำงานพร้อมกันหลายอย่าง
แนะนำ Goroutine, Channel และการทำงานแบบ Concurrent รวมความรู้ก่อนหน้าในการสร้าง Program ที่ทำงานพร้อมกันได้ - Time Package และ Context : การทำงานกับเวลาและบริบท
สอนการใช้ Time Package และ Context ต่อยอดจากการทำงานแบบ Concurrent ในการจัดการงานที่ซับซ้อน - การจัดการการตั้งค่า
สอนการใช้ Environment Variable ใช้ความรู้ในการจัดการ File และข้อมูลในการจัดการการตั้งค่า Program - การทำงานกับเครือข่ายเบื้องต้น
แนะนำการใช้งาน HTTP และ Gin Framework เพื่อสร้าง REST API - การทดสอบขั้นสูง
สอนการทดสอบ Interface และ Mock ต่อยอดการทดสอบเบื้องต้น ในการทดสอบ Program ที่ซับซ้อนขึ้น - การทำงานกับ Database เบื้องต้น
การเชื่อมต่อกับ Database เพื่อสร้าง Application ที่สมบูรณ์ขึ้น - การพัฒนาและ Deploy REST API ด้วย Go และ Docker Container
บูรณาการความรู้จากหลากหลายหัวข้อเพื่อสร้าง REST API ที่มีคุณภาพ
พร้อมที่จะ Go กันหรือยัง? เริ่มต้นการเดินทางของคุณกับ Golang และปลดล็อกศักยภาพในการสร้าง Software ที่ยอดเยี่ยมกันเถอะ!
รู้จักภาษา Go
Go หรือ Golang เป็น Programming Language ที่เป็น Open Source Software ซึ่งพัฒนาโดย Google
Go เปิดตัวอย่างเป็นทางการเมื่อปี พ.ศ. 2552 หรือประมาณ 15 ปีที่ผ่านมา ดังนั้น Go จึงเป็นภาษาที่ใหม่กว่าภาษาอื่น ๆ อย่างเช่น Python, JavaScript และ Java แต่มีอายุมากกว่าภาษา Rust, Kotlin และ Typescript
ภาษาโปรแกรมมิ่งมีวิวัฒนาการจากการป้อนคำสั่งด้วยบัตรเจาะรูในยุคแรก มาเป็นภาษาระดับต่ำที่ใกล้เคียงกับภาษาเครื่อง (Machine Code) ในยุคที่ 2 ซึ่งใช้คำสั่งพื้นฐานที่ CPU เข้าใจได้โดยตรง จนกระทั้งเป็นภาษาที่มนุษย์เข้าใจได้ง่ายขึ้นในยุคที่ 3 ตั้งแต่ทศวรรษ 1950 จนถึงปัจจุบัน
แต่ละภาษามีจุดเด่นและวัตถุประสงค์ที่แตกต่างกัน เช่น บางภาษาเน้นประสิทธิภาพ บางภาษาเน้นความง่ายในการเรียนรู้ ภาษารุ่นใหม่มักพัฒนาต่อยอดจากจุดแข็งของภาษารุ่นก่อน และแก้ไขข้อจำกัดต่างๆ ให้ดีขึ้น
ทศวรรษ 1950 ภาษา Fortran และ LISP นำเสนอแนวคิดใหม่ ๆ เช่น garbage collection และ recursion
ในทศวรรษ 1960 มีการพัฒนาภาษา BASIC ที่ง่ายต่อการเรียนรู้
ทศวรรษ 1970 เกิดภาษาสำคัญ 2 ตัว คือ Smalltalk ที่มีอิทธิพลต่อภาษา Script และภาษาฝั่ง Client และ C ที่พัฒนาขึ้นสำหรับระบบปฏิบัติการ Unix
ทศวรรษ 1980 เป็นยุคของภาษาเชิงวัตถุ (Object-oriented) เช่น Object-C และ C++
ทศวรรษ 1990 เกิดภาษา Python ที่เรียนรู้ง่าย รวมทั้งเกิดภาษาสำคัญอื่น ๆ อีกหลายตัว เช่น Java, JavaScript, PHP และ Ruby
ทศวรรษ 2000 Microsoft เปิดตัว C# พร้อม .NET framework
และทศวรรษ 2010-ปัจจุบัน เกิดภาษาใหม่ในตระกูล C++ คือภาษา D, Rust, Zig, Carbon ในตระกูล Java เกิดภาษา Golang และ Kotlin
เกิด Dart ที่ได้รับความนิยมจาก Flutter และเกิด TypeScript ที่พัฒนาเพื่อทำงานร่วมกับ JavaScript รวมทั้ง Swift ซึ่งพัฒนาโดย Apple เพื่อแทนที่ Objective-C
ทำไม Go ถึงเจ๋ง?
Go ทำงานได้เร็ว เหมือนรถแข่งที่วิ่งได้เร็วกว่ารถทั่วไป (Interpreted Language) ด้วยการ Compile Code เป็นภาษาเครื่องโดยตรง ใช้หน่วยความจำน้อย ทำให้ทำงานเร็ว เหมาะกับการทำงานบน Server
Go เป็นภาษาที่มีประสิทธิภาพสูงเหมือนกับ C++ ที่เป็น Compiled Language เหมือนกัน อย่างไรก็ตามในบางกรณี C++ ก็สามารถมีประสิทธิภาพที่ใกล้เคียงหรือดีกว่าได้
Go มี Garbage Collector ที่ช่วยจัดการหน่วยความจำอัตโนมัติ ลดภาระของนักพัฒนาในการจัดการหน่วยความจำเอง ซึ่งแตกต่างจาก C++ ที่ต้องจัดการหน่วยความจำด้วยตนเอง
Go เรียนรู้ง่าย ไม่ซับซ้อน เหมือนการเรียนรู้วิธีทำแซนด์วิช
ถ้าเรียงระดับภาษาจากสูงไปต่ำ Go จัดเป็นภาษาระดับสูงกว่า C++ และมีไวยกรณ์เรียบง่าย จึงง่ายในการอ่าน ทำความเข้าใจ และเรียนรู้
Python > Go > Rust > C++ > Assembly > Machine Code
Go ทำงานพร้อมกันได้เก่ง เหมือนมีผู้ช่วยหลายคนทำงานให้ Go มี Goroutine ซึ่งเป็นการทำงานแบบ Concurrency ที่มีประสิทธิภาพสูง เนื่องจากมี Overhead ต่ำ และ Channel ช่วยในการสื่อสารระหว่าง Goroutine ทำให้การเขียนโปรแกรม Concurrent ง่ายและปลอดภัย
Go มีชุมชนนักพัฒนาที่ใหญ่และกระตือรือร้น มีคนใช้และช่วยเหลือกันเยอะ มี Package และ Tool มากมาย เช่นที่ https://go.dev และ https://www.reddit.com/r/golang
Go ทำงานกับ Computer ได้หลากหลาย สามารถ Compile สำหรับระบบปฏิบัติการต่าง ๆ ได้ง่าย ทั้ง Windows, Mac, Linux, Raspberry Pi ฯลฯ เหมือนรองเท้าที่ใส่ได้กับทุกชุด
Go Compile ได้เร็ว ช่วยให้พัฒนาและทดสอบได้รวดเร็ว
Go เหมาะกับ Microservice ด้วยความเร็วและประสิทธิภาพ ทำให้เหมาะกับการสร้าง Microservice
Go เป็นภาษาที่ผสมผสานหลายแนวคิดเข้าด้วยกัน ทั้งแบบ Procedural โดยการสนับสนุนการเขียน Code เป็นลำดับขั้นตอน เหมือนการทำตามสูตรอาหาร และแบบ Functional โดย Go สามารถส่ง Function เป็น Parameter เหมือนการส่งเครื่องมือให้เพื่อนใช้
Go ไม่ใช่ภาษา Object-oriented แบบดั้งเดิม แต่มี Struct, Method และ Interface ที่ทำงานได้คล้าย ๆ กัน
สรุปแล้ว Go เป็นภาษาที่ยืดหยุ่น ผสมผสานหลายแนวคิดเข้าด้วยกัน แต่เน้นความเรียบง่ายและมีประสิทธิภาพ เป็นเหมือนมีด Swiss ที่ทำได้หลายอย่าง ใช้งานง่าย แต่ทรงพลัง ทำให้เป็นตัวเลือกที่ดีสำหรับพัฒนา Back End โดยเฉพาะระบบที่ต้องการประสิทธิภาพสูงและรองรับผู้ใช้จำนวนมาก เช่น E-commerace Platform ครับ
ABC ของ Go
Go Get Started
ในการเริ่มใช้ Go เราต้องมี 2 สิ่งต่อไปนี้ คือ
- Text Editor เช่น VS Code สำหรับเขียน Code
- Go Compiler สำหรับแปล Go Code เป็นภาษาที่ Computer สามารถเข้าใจได้
ให้ Download ทั้ง Text Editor และ Go Compiler แล้วติดตั้งโดยปฏิบัติตามคำแนะนำตามระบบปฏิบัติการของคุณ
เมื่อติดตั้ง Go Compiler แล้ว ให้ตรวจสอบความสมบูรณ์ของ Go Compiler โดยใช้คำสั่ง go version ใน Command Line
go version
สร้าง Folder hellogo สำหรับ Project แรกของเรา โดยใช้คำสั่ง mkdir hellogo แล้วเปิด VS Code ด้วยคำสั่ง code .
อย่างไรก็ตามถ้าหากยังไม่สามารถใช้คำสั่ง code . ผ่าน Command Line เพื่อเปิด VS Code ได้ให้ตั้งค่า VS Code ดังต่อไปนี้
- เปิด VS Code
- กด CMD + SHIFT + p
- พิมพ์ shell command
- เลือก Install 'code' Command in PATH
ติดตั้ง Go Extension บน VS Code ดังต่อไปนี้
- กด CMD + SHIFT + x
- พิมพ์ go
- กดติดตั้ง Go Extension ของ Google (Go Team at Google)
4. หลังจากกด Install แล้ว กด CMD + SHIFT + p อีกครั้ง
5. พิมพ์ go install
6. เลือก Update Tools
หลังจากติดตั้ง Go Extension แล้วให้สร้าง File hello_world.go
package main
import ("fmt")
func main() {
fmt.Println("Hello World!")
}
Copy Code ด้านบนไปวางใน File hello_world.go แล้ว Save File
ตอนนี้เราสามารถ Run Go Code แรก บน Terminal ของ VS Code ด้วยคำสั่ง go run ได้แล้ว
go run hello_world.go
ขณะที่การ Compile Go Code ให้เป็นภาษาเครื่องเราจะใช้คำสั่ง go build
go build hello_world.go
Go Compiler จะสร้าง Binary File ซึ่งเราสามารถรัน Program ได้โดยใช้คำสั่ง ./hello_world ครับ
ตัวแปรและชนิดข้อมูล : กล่องใส่ของชนิดต่าง ๆ
ตัวแปร เหมือนกับกล่องใส่ของ แต่ละกล่องเก็บของได้ไม่เหมือนกัน
var age int = 25
name := "Nuttachot"
การประกาศตัวแปรใน Go ทำได้ 2 แบบ คือ ประกาศแบบชัดเจน และประกาศแบบอัตโนมัติ
ตัวอย่างชนิดข้อมูลพื้นฐานของ Go 4 ชนิด ได้แก่ int, float64, string และ bool
การพิมพ์ข้อความ : fmt หรือ Format
ใช้ fmt.Println หรือ fmt.Printf เพื่อบอกให้ Computer แสดงข้อความบนหน้าจอ
fmt.Println("สวัสดี, Go!")
fmt.Printf("ฉันอายุ %d ปี\n", age)
fmt.Println สำหรับพิมพ์ข้อความและขึ้นบรรทัดใหม่ ขณะที่ fmt.Printf สำหรับพิมพ์ข้อความตามรูปแบบที่กำหนด เช่น %d, %f, %s และ %t
Comment : เขียน Note ให้ตัวเองหรือเพื่อนร่วมงาน
Comment ใน Go มี 2 แบบ คือ Comment บรรทัดเดียว และ Comment หลายบรรทัด
ตัวดำเนินการพื้นฐาน และการเปรียบเทียบ
ตัวดำเนินการพื้นฐาน 5 ตัวดำเนินการ และตัวดำเนินการเปรียบเทียบ 6 ตัวดำเนินการ ของ Go มีดังนี้
Exercise
เขียนโค้ดสั้น ๆ ที่มีการประกาศตัวแปร พิมพ์ข้อความ ใช้ Comment และตัวดำเนินการ
ตัวอย่างโค้ด
package main
import "fmt"
func main() {
// ประกาศตัวแปร
age := 25
name := "Nuttachot"
// พิมพ์ข้อความ
fmt.Println("สวัสดี, Go!")
fmt.Printf("%s อายุ %d ปี\n", name, age)
// การคำนวณ
result := age * 2
fmt.Printf("อายุ 2 เท่า : %d\n", result)
}
Go Quiz 1 (20 ข้อ) ขอให้สนุกกับการทำ Quiz นะครับ
Q&A?
รวม Cheat Sheet ABC ของ Go
ABC ของ Go
----------
1. การประกาศตัวแปรใน Go
- ประกาศแบบชัดเจน (var ชื่อตัวแปร ชนิดข้อมูล = ค่า)
var age int = 25
- ประกาศแบบอัตโนมัติ (ชื่อตัวแปร := ค่า)
name := "Nuttachot"
2. ชนิดข้อมูลพื้นฐาน
- int จำนวนเต็ม เช่น 1, 2 และ 3
- float64 ทศนิยม เช่น 3.14 และ 2.5
- string ข้อความ เช่น "Hello" และ "Go"
- bool ค่าความจริง ได้แก่ true และ false
3. การพิมพ์ข้อความ
- fmt.Println("ข้อความ") // พิมพ์ข้อความและขึ้นบรรทัดใหม่
- fmt.Printf("รูปแบบ", ค่า) // พิมพ์ข้อความตามรูปแบบที่กำหนด
%d จำนวนเต็ม
%f ทศนิยม
%s ข้อความ
%t boolean
%T ประเภทของตัวแปร
%v ค่าของตัวแปรในรูปแบบ Default
เช่น
fmt.Printf("ฉันอายุ %d ปี", age)
4. Comment
// นี่คือ comment บรรทัดเดียว
/*
นี่คือ comment
หลายบรรทัด
*/
5. ตัวดำเนินการพื้นฐาน
+ บวก
- ลบ
* คูณ
/ หาร
% หารเอาเศษ
6. การเปรียบเทียบ
== เท่ากับ
!= ไม่เท่ากับ
< น้อยกว่า
> มากกว่า
<= น้อยกว่าหรือเท่ากับ
>= มากกว่าหรือเท่ากับ
การตัดสินใจใน Code
ใน Go เราใช้ if, else, for loop และ switch ทำให้ Program ตัดสินใจได้ด้วยตัวเอง
if : การถามคำถาม ถ้าคำตอบใช่ ทำอย่างหนึ่ง ถ้าคำตอบไม่ใช่ ทำอีกอย่าง
age := 18
if age >= 18 {
fmt.Println("คุณสามารถเข้าชมได้")
} else {
fmt.Println("คุณอายุน้อยเกินไป")
}
// ประโยค (statements) ที่อยู่ในเงื่อนไข if และ else จำเป็นต้องอยู่ภายใน {} เสมอ
// แม้ว่าจะมีเพียงคำสั่งเดียว เพื่อเพิ่มความชัดเจนในการอ่านโค้ด
นอกจาก if, else แล้ว ยังมี if, else if เพื่อใช้ถามได้มากกว่า 2 เงื่อนไขครับ
for loop
for loop ใช้เมื่อเราต้องการทำอะไรซ้ำ ๆ หลายครั้ง
// นับ 1 ถึง 5
for i := 1; i <= 5; i++ {
fmt.Println(i)
}
// while-like loop
count := 0
for count < 3 {
fmt.Println("นับ:", count)
count++
}
for loop ใน Go มี 3 แบบหลัก ๆ คือ แบบมาตรฐาน ที่มี ค่าเริ่มต้น; เงื่อนไข; การเปลี่ยนแปลง คล้ายกับภาษา C, C++, และ Java แบบ while และแบบ for range
จะเห็นว่า for loop ของ Go ค่อนข้างมีความยืดหยุ่นเนื่องจากมีรูปแบบการใช้งานที่หลากหลายและไม่จำเป็นต้องใช้วงเล็บที่เงื่อนไข
break และ continue
Break ใช้เพื่อออกจาก Loop ทันที!
for i := 1; i <= 10; i++ {
if i == 5 {
fmt.Println("เจอเลข 5 ออกจากลูป!")
break
}
fmt.Println(i)
}
fmt.Println("จบโปรแกรม")
Continue ใช้เพื่อข้ามการทำงานที่เหลือในรอบนั้น และไปเริ่มรอบถัดไปทันที
for i := 1; i <= 5; i++ {
if i == 3 {
fmt.Println("ข้ามเลข 3!")
continue
}
fmt.Println(i)
}
fmt.Println("จบโปรแกรม")
ตัวอย่างการใช้ทั้ง Break และ Cotinue ร่วมกัน
for i := 1; i <= 10; i++ {
if i%2 == 0 {
fmt.Println("ข้ามเลขคู่:", i)
continue
}
if i > 7 {
fmt.Println("เจอเลขมากกว่า 7 ออกจากลูป!")
break
}
fmt.Println("เลขคี่:", i)
}
fmt.Println("จบโปรแกรม")
switch
switch ใช้เมื่อมีหลายทางเลือก แทนการใช้ if-else ซ้อนกันหลายชั้น
day := "จันทร์"
switch day {
case "จันทร์":
fmt.Println("วันต้นสัปดาห์")
case "ศุกร์":
fmt.Println("ใกล้วันหยุดแล้ว")
default:
fmt.Println("วันธรรมดา")
}
switch ใน Go จะไม่ทำงานตกลงมาใน Case ถัดไปโดยอัตโนมัติหากไม่มีการใช้คำสั่ง fallthrough ซึ่งต่างจาก C, C++, และ Java ที่จะต้องใช้คำสั่ง break เพื่อป้องกันการตกลงมาใน case ถัดไป
Exercise
เขียน Code สั้น ๆ ที่ใช้ if-else และ for loop
Go Quiz 2 (10 ข้อ) ขอให้สนุกกับการทำ Quiz นะครับ
Q&A?
รวม Cheat Sheet การตัดสินใจใน Code
การตัดสินใจใน Go
--------------
1. if-else
if เงื่อนไข {
// ทำเมื่อเงื่อนไขเป็นจริง
} else {
// ทำเมื่อเงื่อนไขเป็นเท็จ
}
// หลายเงื่อนไข
if เงื่อนไข1 {
// ทำเมื่อเงื่อนไข1 เป็นจริง
} else if เงื่อนไข2 {
// ทำเมื่อเงื่อนไข2 เป็นจริง
} else {
// ทำเมื่อไม่มีเงื่อนไขใดเป็นจริง
}
2. for loop
// แบบมาตรฐาน
for ค่าเริ่มต้น; เงื่อนไข; การเปลี่ยนแปลง {
// ทำซ้ำๆ
}
// แบบ while
for เงื่อนไข {
// ทำซ้ำๆ ตราบใดที่เงื่อนไขเป็นจริง
}
// วนลูปไม่สิ้นสุด
for {
// ทำซ้ำๆ ตลอดไป (ต้องใช้ break เพื่อออกจากลูป)
}
3. switch
switch ตัวแปร {
case ค่า1:
// ทำเมื่อตัวแปรมีค่าเท่ากับ ค่า1
case ค่า2:
// ทำเมื่อตัวแปรมีค่าเท่ากับ ค่า2
default:
// ทำเมื่อไม่ตรงกับค่าใดเลย
}
4. คำสั่งพิเศษ
break // ออกจากลูปทันที
continue // ข้ามไปรอบถัดไปของลูป
Function : วิธีทำสิ่งต่าง ๆ ที่ใช้ซ้ำได้
Function ใน Go เปรียบเสมือนเครื่องมือที่เราสร้างขึ้นเพื่อทำงานเฉพาะอย่าง และเราสามารถทำซ้ำได้ตามต้องการ
การสร้างและเรียกใช้ Function
Function เหมือนสูตรอาหาร ที่บอกวิธีทำอะไรบางอย่าง
func sayHello() {
fmt.Println("สวัสดี, Go!")
}
func main() {
sayHello()
sayHello()
}
Function ใน Go ถูกประกาศโดยใช้คำว่า func ตามด้วย ชื่อ Function
ชื่อ Function ขึ้นต้นด้วยตัวพิมพ์ใหญ่เพื่อให้เรียกใช้ได้จาก Package อื่น และขึ้นต้นด้วยตัวพิมพ์เล็ก เมื่อต้องการเรียกใช้เฉพาะภายใน Package
// เรียกใช้ได้จาก Package อื่น
func ValidateUser(id string) error {}
// เรียกใช้ได้เฉพาะภายใน Package
func validateUserEmail(email string) bool {}
Parameter และ Return Value
Parameter คือข้อมูลที่เราส่งเข้าไปใน Fucntion ส่วน Return Value คือผลลัพธ์ที่ Function ส่งกลับมา
func greet(name string) {
fmt.Println("สวัสดี,", name)
}
func add(a, b int) int {
return a + b
}
func main() {
greet("Nuttachot")
result := add(5, 3)
fmt.Println("5 + 3 =", result)
}
การใช้งาน Function ใน Go มีความคล้ายคลึงกับการใช้งานในภาษาอื่น ๆ แต่ก็มีลักษณะเฉพาะที่ทำให้ Go มีความแตกต่างในบางด้าน
Go สนับสนุนการคืนค่าหลายค่าจาก Function ซึ่งต่างจากภาษา C และ C++ ที่สามารถคืนค่าได้เพียงค่าหนึ่ง (เว้นแต่จะใช้ struct)
func swap(x, y string) (string, string) {
return y, x
}
Go มี Feature การตั้งชื่อผลลัพธ์ใน Function ซึ่งทำให้สามารถคืนค่าผลลัพธ์ได้โดยไม่ต้องระบุชื่อของตัวแปรในคำสั่ง return
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
Go มีความยืดหยุ่นในการใช้งานฟังก์ชันและมีลักษณะการเขียนที่คล้ายคลึงกับหลาย ๆ ภาษา เช่น C++, Python, Java และ JavaScript
First-Class Citizen Function
Function ใน Go จะมีสถานะเทียบเท่ากับข้อมูลประเภทอื่น ที่สามารถจัดการได้เหมือนกับตัวแปรทั่วไป
First-Class Citizen Function ใน Go มีความคล้ายคลึงกับภาษาอื่น ๆ หลายภาษา เช่น C++, Python, Java และ JavaScript แต่มีความเรียบง่าย ทำให้ Go เป็นตัวเลือกที่ดีสำหรับการเขียน Program แบบ Functional ในขณะที่ยังคงรักษาประสิทธิภาพและความชัดเจนของ Code
ความสามารถหลัก ๆ ของ First-Class Citizen Function ใน Go ได้แก่
1. สามารสร้างและใช้งาน Anonymous Function หรือ Function ที่ไม่มีชื่อได้
func main() {
// Anonymous function
func() {
fmt.Println("ฉันเป็น anonymous function")
}()
}
เราสร้างมันขึ้นมาเพื่อทำงานบางอย่างได้ทันทีโดยไม่ต้องตั้งชื่อ และไม่ต้องสร้าง Function แยกต่างหาก ซึ่งเหมาะสำหรับงานที่ใช้ครั้งเดียวแล้วไม่ใช้อีก
2. สามารถกำหนด Function ให้กับตัวแปรได้
func main() {
// กำหนดฟังก์ชันให้กับตัวแปร
sayHello := func(name string) {
fmt.Println("สวัสดี,", name)
}
// เรียกใช้ฟังก์ชันผ่านตัวแปรภายหลัง
sayHello("อลิซ")
}
จากตัวอย่างเราสร้าง Anonymous Function เก็บไว้ในตัวแปร sayHello เพื่อนำไปใช้ภายหลัง
3. สามารถส่ง Function เป็นพารามิเตอร์ให้กับ Function อื่นได้
func doTwice(f func(string), message string) {
f(message)
f(message)
}
func main() {
printMessage := func(msg string) {
fmt.Println(msg)
}
doTwice(printMessage, "สวัสดีชาวโลก")
}
จากตัวอย่าง การส่ง Function เป็นพารามิเตอร์ (ตัวแปร printMessage) ให้กับ Function อื่นได้ ทำให้เราสามารถสร้าง Function doTwice ที่มีความยืดหยุ่นสูง ด้วยการกำหนดพฤติกรรมได้จากภายนอก โดยไม่ต้องแก้ไข Code ภายใน Function หลัก
4. สามารถคืนค่าเป็น Function ได้
func createMultiplier(factor int) func(int) int {
return func(n int) int {
return n * factor
}
}
func main() {
doubler := createMultiplier(2)
tripler := createMultiplier(3)
fmt.Println(doubler(5)) // 10
fmt.Println(tripler(5)) // 15
}
จากตัวอย่างเราสามารถสร้าง Function ที่เก็บในตัวแปร doubler และ tripler ที่สามารถปรับแต่งได้ตามพารามิเตอร์ที่ส่งเข้าไป
5. สามารถสร้าง Closure Function ได้
Closure หรือ Function ปิด คือกล่องวิเศษที่จำค่าบางอย่างไว้ แม้ว่าเราจะปิดกล่องไปแล้ว
func createCounter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
counter := createCounter()
fmt.Println(counter()) // 1
fmt.Println(counter()) // 2
fmt.Println(counter()) // 3
}
จากตัวอย่างเราสร้าง Closure Function ที่เก็บในตัวแปร counter ซึ่งจำค่า count ได้ แม้เรียกใช้งานมันไปแล้ว
Closure ทำให้เราสามารถสร้างฟังก์ชันที่มีสถานะ (Stateful Function) ช่วยในการ Encapsulate ข้อมูล ลดการใช้ตัวแปรส่วนกลาง (Global Variable) ได้ แต่อาจใช้หน่วยความจำมากขึ้น เพราะตัวแปรที่ถูกอ้างอิงโดย Closure จะไม่ถูกทำลายหลังจาก Function ภายนอกทำงานเสร็จ ทำให้ใช้หน่วยความจำนานกว่าปกติ นอกจากนี้หากเราสร้าง Closure หลายตัวที่อ้างอิง Function เดียวกัน Closure แต่ละตัวจะมีสำเนาของสภาพแวดล้อมของตัวเอง
ดังนั้น doubler และ tripler จากตัวอย่างก่อนหน้า ก็เป็น Closure Function ที่เก็บค่า factor ต่างกัน และสามารถใช้ค่านี้ในการคำนวณเมื่อถูกเรียกใช้
แม้ว่า Closure จะเก็บสถานะของตัวแปรไว้ แต่ Go มี Garbage Collector ที่ช่วยจัดการหน่วยความจำ ทำให้ไม่ต้องกังวลเรื่อง Memory Leak มากนัก
นอกจากนี้ถึงแม้ว่า Closure จะใช้หน่วยความจำมากขึ้น แต่ประโยชน์ในแง่ของความยืดหยุ่นและการเขียน Code ที่สะอาดก็มีมาก การใช้ Closure เฉพาะเมื่อจำเป็น จะช่วยให้ได้ประโยชน์สูงสุด
Init Function
init() เป็น Function พิเศษที่จะทำงานโดยอัตโนมัติก่อนที่ Function main() จะเริ่มทำงาน เราสามารถเปรียบเทียบมันเหมือนกับการที่พ่อครัวต้องเตรียมวัตถุดิบและอุปกรณ์ต่างๆ ให้พร้อมก่อนลงมือทำอาหารจริง ๆ โดย Function init() ไม่สามารถรับค่าหรือ Return ค่าได้
package main
import "fmt"
func init() {
fmt.Println("กำลังเตรียมความพร้อม...")
}
func main() {
fmt.Println("เริ่มการทำงานของโปรแกรมหลัก...")
}
// ผลลัพธ์
// กำลังเตรียมความพร้อม...
// เริ่มการทำงานของโปรแกรมหลัก...
ลักษณะเด่นที่สำคัญของ init() มีดังนี้
- Go จะเรียกใช้ Function init() โดยอัตโนมัติ
- สามารถมี Function init() ได้หลาย Function
package main
import "fmt"
func init() {
fmt.Println("เตรียมความพร้อม 1...")
}
func init() {
fmt.Println("เตรียมความพร้อม 2...")
}
func main() {
fmt.Println("เริ่มการทำงานของโปรแกรมหลัก...")
}
// ผลลัพธ์
// เตรียมความพร้อม 1...
// เตรียมความพร้อม 2...
// เริ่มการทำงานของโปรแกรมหลัก...
ลำดับการทำงานของ Function init()
1) Function init() ของ Package ที่ถูก Import จะทำงานก่อน
2) ตัวแปร Global ใน Package ปัจจุบันจะถูกกำหนดค่า
3) Function init() ของ Package ปัจจุบันจะทำงาน
// helper/helper.go
package helper
import "fmt"
func init() {
fmt.Println("กำลังเตรียม Package helper...")
}
func SayHello() {
fmt.Println("Hello from SayHello function...")
}
// main.go
package main
import (
"fmt"
"myproject/helper"
)
var globalVar = initGlobal()
func initGlobal() string {
fmt.Println("กำลังกำหนดค่าตัวแปร Global...")
return "initialized"
}
func init() {
fmt.Println("กำลังเตรียม Package main...")
}
func main() {
fmt.Println("เริ่มการทำงานของโปรแกรมหลัก...")
}
// ผลลัพธ์
// กำลังเตรียม Package helper...
// กำลังกำหนดค่าตัวแปร Global...
// กำลังเตรียม Package main...
// เริ่มการทำงานของโปรแกรมหลัก...
// Hello from SayHello function...
Exercise
เขียนฟังก์ชันง่าย ๆ ที่รับชื่อและอายุ แล้วพิมพ์ประโยคทักทาย
Go Quiz 3 (17 ข้อ) ขอให้สนุกกับการทำ Quiz นะครับ
Q&A?
รวม Cheat Sheet Function
Function
--------
1. การสร้าง Function พื้นฐาน
func ชื่อฟังก์ชัน() {
// Code ที่ต้องการให้ทำงาน
}
2. Function กับ Parameter
func ชื่อฟังก์ชัน(param1 type1, param2 type2) {
// ใช้ param1 และ param2 ใน Function
}
3. Function กับ Return Value
func ชื่อฟังก์ชัน() returnType {
// โค้ด
return ค่าที่ต้องการส่งกลับ
}
4. Function กับหลาย Return Value
func ชื่อฟังก์ชัน() (returnType1, returnType2) {
// โค้ด
return ค่า1, ค่า2
}
5. Function กับการตั้งชื่อผลลัพธ์
func ชื่อฟังก์ชัน() (resultName returnType) {
// โค้ด
return // ไม่ต้องระบุชื่อของตัวแปรในคำสั่ง return
}
6. Anonymous Function (ฟังก์ชันไม่มีชื่อ)
func() {
// Code ภายใน Function
}()
7. กำหนด Function ให้กับตัวแปร เช่น
myFunc := func(param Type) {
// โค้ดภายในฟังก์ชัน
}
8. ส่ง Function เป็น Parameter เช่น
func ชื่อฟังก์ชัน(f func(Type1), param Type2) {
f(param) // Type1 และ Type2 เป็นชนิดเดียวกัน
}
9. คืนค่าเป็น Function เช่น
func ชื่อฟังก์ชัน(param1 Type1) func(Type2) returnType {
return func(param2 Type2) returnType {
// โค้ดภายในฟังก์ชัน
return returnType
}
}
10. Closure เช่น
func ชื่อฟังก์ชัน() func() returnType {
// outer variables
return func() returnType {
// code using outer variables
return returnType
}
}
11. Function พิเศษที่จะทำงานโดยอัตโนมัติก่อนที่ Function main() จะเริ่มทำงาน
Function init()
func init() {
// โค้ดภายในฟังก์ชัน
}
พบกับ Mastering Golang for E-commerce Back End Development : Part 2 เร็ว ๆ นี้ครับ