การเขียนโปรแกรม ภาษา Go เบื้องต้น
เรียนรู้พื้นฐานภาษา Go ครอบคลุมแนวคิดการเขียนโปรแกรมพื้นฐานของภาษา Go
ภาษา Go เป็นโปรแกรมโอเพ่นซอร์ส ที่ทำให้ง่ายต่อการสร้างซอฟต์แวร์ที่เรียบง่าย เชื่อถือได้ และมีประสิทธิภาพ โดย Go เป็นภาษาการเขียนโปรแกรมคอมไพล์ที่สร้างโดย Google
ข้อกำหนดเบื้องต้น
ข้อกำหนดสำหรับบทความนี้คือ คุณต้องติดตั้ง Go บนคอมพิวเตอร์ของคุณตามบทความ ติดตั้ง Go และ ทดสอบ Hello World มาก่อน
การตั้งชื่อ (Go Identifier)
ภาษา Go มีกฎในการตั้งชื่อให้กับ Identifier คือคำที่ตั้งขึ้นมาเพื่อกำหนดให้เป็นชื่อโปรแกรม โปรแกรมย่อย ตัวแปร ชนิด ข้อมูล และค่ำคงตัว ยูนิต รวมทั้งฟิลด์ในระเบียน (record)
หลักการตั้งชื่อในภาษา Go คือชื่อสำหรับตัวแปร ฟังก์ชัน คลาส หรือพารามิเตอร์ ชื่อสามารถมีอักขระที่เป็นตัวอักษรและตัวเลขคละกันและขีดล่างได้ การขึ้นต้นชื่อตัวแปรด้วยตัวเลขถือเป็นข้อผิดพลาด และ Go ไม่อนุญาตให้เว้นวรรคในชื่อ
ชื่อจะคำนึงถึงขนาดตัวพิมพ์ ซึ่งหมายความว่า Name, name, และ NAME อ้างถึงตัวแปรที่แตกต่างกัน 3 ตัว และชื่อไม่สามารถใช้ซ้ำกับ คำหลัก (Go Keywords) ของภาษา Go ได้
มี Go Keywords ทั้งหมด 25 คำในภาษา Go ดังนี้
break , case , chan , const , continue , default , defer , else, fallthrough , for , func , go , goto , if , import , interface , map , package , range , return , select , struct , switch , type , var
แบ่งแยกคำสั่ง (Go white space)
White Space in Go ใช้เพื่อแยกโทเค็นในโปรแกรม White space คือ ตัวอักษรหรือเครื่องหมายที่ใช้แบ่งแยกคำสั่งและ Token ในโค้ดของโปรแกรม ใน ภาษา Go นั้น white space จะประกอบไปด้วย การเว้นวรรค Tab และการขึ้นบรรทัดใหม่ White space ที่เรียงต่อกันเป็นจำนวนมากนั้นไม่มีผลต่อการทำงานของโปรแกรมและคอมไพเลอร์ แต่มันช่วยให้โปรแกรมเมอร์สามารถทำโค้ดให้เป็นระเบียบและสามารถอ่านเข้าใจได้ เช่น
จำเป็นต้องมี White space ในบางสถานที่ ตัวอย่างเช่น ระหว่าง คำหลัก var กับตัวแปร i และ i กับ int เป็นต้น
var i int = 0
จำนวนช่องว่างระหว่างโทเค็นไม่มีผลกับคอมไพเลอร์ของ Go แต่ควรใช้ White space อย่างสม่ำเสมอในโปรแกรม Go
var i int=1
var j int = 2
var k int = 3
Go ตัวอย่างแรก
สร้างโฟลเดอร์ใหม่สำหรับการเรียนรู้ สร้างแอพพลิเคชั่นพื้นฐาน ชื่อ first ที่ GOPATH ในตัวอย่างคือ C:/User/ชื่อผู้ใช้/go/src/first
สร้างไฟล์ Go Modules ด้วยคำสั่ง
go mod init first
สร้างไฟล์ first.go เริ่มต้นโมดูล Go ด้วยโปรแกรม Go ธรรมดาที่พิมพ์ข้อความไปยังคอนโซล
package main
import "fmt"
func main() {
fmt.Println("Go first example")
}
โค้ดถูกจัดระเบียบโดยคำหลัก package และโปรแกรมจะเริ่มทำงานที่แพ็คเกจ main
package main
แพ็คเกจจะเข้ามาอยู่ในโปรแกรมด้วยคำหลัก import ชื่อแพ็คเกจคือ fmt ประกอบด้วยฟังก์ชัน อินพุต เอาต์พุต ที่จัดรูปแบบข้อความไปยังคอนโซล
import "fmt"
ภายในแพ็คเกจ main จะมีฟังก์ชันชื่อ main และนี่คือจุดเริ่มต้นของโปรแกรม Go โดยฟังก์ชั่นถูกสร้างขึ้นด้วยคำหลัก func (มาจากคำเต็มว่า function)
func main() {
จากแพ็คเกจ fmt เราใช้ ฟังก์ชัน Println เพื่อแสดงข้อความ ขอให้สังเกตว่าคำสั่งนี้ไม่สิ้นสุดด้วยเครื่องหมาย ; ซึ่งไม่เหมือนกับภาษาอื่นๆ เช่น Java, C หรือ C#
fmt.Println("Go first example")
เราคอมไพล์และรันโปรแกรมในครั้งเดียวด้วยคำสั่ง go run first.go
go run first.go
คอมเมนต์ (Go comments)
คอมเมนต์ (comments) คือส่วนที่เป็นหมายเหตุของโปรแกรม มีไว้เพื่อให้ผู้เขียนโปรแกรมใส่ข้อความอธิบายกำกับลงไปใน source code ซึ่งคอมไพเลอร์จะข้ามการแปลผลในส่วนที่เป็นคอมเมนต์นี้ คอมเมนต์ในภาษา Go มี 2 แบบคือ
• คอมเมนต์แบบบรรทัดเดียว ใช้เครื่องหมาย //
• คอมเมนต์แบบหลายบรรทัด ใช้เครื่องหมาย /* และ */
การประกาศตัวแปร (Variable)
ตัวแปร (variable) ใช้เพื่อเก็บค่า เป็นฉลากที่กำหนดให้กับค่า Go ใช้คำหลัก var เพื่อประกาศรายการตัวแปร นอกจากนี้เรายังสามารถใช้การประกาศตัวแปรแบบสั้น (Shorthand) := เพื่อประกาศตัวแปรได้อีกด้วย
ตัวแปรสามารถเก็บค่าของประเภทข้อมูลต่างๆ ได้ ชนิดข้อมูลคือชุดของค่าและการดำเนินการที่อนุญาตสำหรับค่าเหล่านั้น ในหลายกรณี Go สามารถสรุปประเภทข้อมูลจากด้านขวาของงานได้
ตัวแปรแบบกําหนดค่า
ในตัวอย่างโค้ด เราประกาศและเริ่มต้นตัวแปรสองตัว จากนั้นจึงพิมพ์ออกมา ตัวแปรแรกถือจำนวนเต็ม ตัวที่สองเป็นทศนิยม ชนิดข้อมูลตามชื่อตัวแปรใน Go
package main
import "fmt"
func main() {
var i int = 1
var w float64 = 12.5
fmt.Println(i, w)
}
ตัวแปรแบบ Type อัตโนมัติ
Go สามารถอนุมานประเภทข้อมูลจากด้านขวาของงานได้ ในตัวอย่างโค้ด เรากำหนดตัวแปรสองตัวโดยไม่ระบุประเภทข้อมูล ชนิดข้อมูลจะถูกอนุมาน กําหนด Type ของตัวแปรนั้นๆให้โดยอัตโนมัติตามข้อมูลที่เรากําหนด
package main
import (
"fmt"
"reflect"
)
func main() {
var name = "John Doe"
var age = 34
fmt.Println(reflect.TypeOf(name))
fmt.Println(reflect.TypeOf(age))
fmt.Printf("%s is %d years old\n", name, age)
}
เพื่อให้การอนุมานทำงาน ตัวแปรต้องได้รับการเตรียมข้อมูลเบื้องต้น
var name = "John Doe"
var age = 34
ด้วยความช่วยเหลือของฟังก์ชัน TypeOf จากแพ็คเกจ reflect เราพิมพ์ประเภทข้อมูลของตัวแปรทั้งสอง
fmt.Println(reflect.TypeOf(name))
fmt.Println(reflect.TypeOf(age))
ทดสอบการทำงาน
ตัวแปรแบบสั้น (Shorthand)
การประกาศตัวแปรแบบสั้น (Shorthand) ซึ่งการประกาศตัวแปรแบบนี้จะนิยมและเห็นบ่อยที่สุด
ตัวอย่างประกาศตัวแปร 2 ตัวด้วย การประกาศตัวแปรแบบสั้น คือการตัดคําว่า var ออก แล้วเติม “:” ข้างหน้าเครื่องหมาย “=” มาดูตัวอย่างกัน
package main
import "fmt"
func main() {
name := "John Doe"
age := 34
fmt.Printf("%s is %d years old", name, age)
}
อินพุตของผู้ใช้
ฟังก์ชัน Scanf จะสแกนข้อความที่อ่านจากอินพุตมาตรฐาน โดยจัดเก็บค่าที่คั่นด้วยช่องว่างที่ต่อเนื่องกันลงในอาร์กิวเมนต์ที่ต่อเนื่องกันตามที่กำหนดโดยรูปแบบ แล้วส่งคืนจำนวนรายการที่สแกนสำเร็จ
ตัวอย่างจะแจ้งให้ผู้ใช้ป้อนชื่อของเขา
package main
import "fmt"
func main() {
var name string
fmt.Print("Enter your name: ")
fmt.Scanf("%s", &name)
fmt.Println("Hello", name)
}
เรากำหนดตัวแปรสตริง
var name string
ค่าที่ป้อนจะถูกเก็บไว้ในตัวแปร name
fmt.Scanf("%s", &name)
เรียกใช้โปรแกรมและป้อนชื่อ
การใช้เงื่อนไข if else
เงื่อนไขถูกสร้างขึ้นด้วยคำหลัก if, else if, และ else
ในตัวอย่างนี้ เราสุ่มค่าระหว่าง -5 ถึง 4 ด้วยความช่วยเหลือของเงื่อนไข เราจะพิมพ์ข้อความสำหรับทั้ง 3 ตัวเลือก คือ มากกว่า 0 , เท่ากับ 0 และ น้อยกว่า 0
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
num := -5 + rand.Intn(10)
if num > 0 {
fmt.Println("The number is positive")
} else if num == 0 {
fmt.Println("The number is zero")
} else {
fmt.Println("The number is negative")
}
}
เราเรียกใช้ตัวอย่างสองสามครั้ง
การใช้ Loop
Go จะเน้นความกระชับของภาษา ดังนั้น Go จึงมีแค่ for loop แต่ถ้าอยากจะใช้ loop แบบอื่นๆ ก็สามารถทําได้เช่นกัน
คำสั่ง for ระบุการดำเนินการซ้ำของบล็อก
นี่คือสไตล์ ภาษา C แบบคลาสสิก สำหรับคำสั่ง โปรแกรมคำนวณผลรวมของค่า 1..9
package main
import "fmt"
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
}
คำสั่ง for ประกอบด้วยสามส่วน: การเริ่มต้น, เงื่อนไข และการเพิ่มขึ้น ส่วนการเริ่มต้นจะดำเนินการเพียงครั้งเดียว เนื้อความของคำสั่ง for จะดำเนินการเมื่อเงื่อนไขเป็นจริง ถ้าเงื่อนไขคืนค่าเป็นเท็จ for วนรอบจะถูกยกเลิก หลังจากที่ดำเนินการคำสั่งในบล็อกแล้ว for loop จะสลับไปยังส่วนที่สาม โดยที่ตัวนับจะเพิ่มขึ้น วงจรจะดำเนินต่อไปจนกว่าเงื่อนไขจะไม่เป็นจริงอีกต่อไป โปรดทราบว่าคุณสามารถสร้างการวนซ้ำไม่รู้จบได้
for i := 0; i < 10; i++ {
sum += i
}
ผลรวมของค่า 1..9 คือ 45
ตัวอย่างต่อไปนี้ใช้ for ลูปกับ range คำนวณผลรวมของค่าอาร์เรย์
package main
import "fmt"
func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println(sum)
}
เรากำหนดค่าของอาร์เรย์
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
เราวนซ้ำในอาร์เรย์ด้วยส่วนคำสั่ง range และ range ส่งคืนดัชนีและค่าในการวนซ้ำแต่ละครั้ง
เนื่องจากเราไม่ได้ใช้ index เราจึงต้องระบุตัวดำเนินการเป็น _ (discard operator) คือ ไม่ต้องดำเนินการ เพื่อให้ code ที่เขียน compile ผ่าน ซึ่งเอกสาร Golang เรียก _ ว่า blank identifier
for _, num := range nums {
sum += num
}
ดำเนินการแบบหลายทาง (Go switch)
คำสั่ง Go switch ให้การดำเนินการแบบหลายทาง นิพจน์หรือตัวระบุประเภทจะถูกเปรียบเทียบกับเคสภายในสวิตช์เพื่อกำหนด statement ที่จะดำเนินการ ไม่เหมือนกับภาษาอื่นๆ เช่น C, Java หรือ PHP โดยแต่ละกรณีจะสิ้นสุดลงด้วยการ break โดยปริยาย เราจึงไม่ต้องเขียน break
คำสั่งเริ่มต้นสามารถใช้สำหรับ statement ที่ดำเนินการ เมื่อไม่มีกรณีอื่นที่เหมาะสม คำสั่งเริ่มต้นเป็นทางเลือก
package main
import (
"fmt"
"runtime"
)
func main() {
os := runtime.GOOS
switch os {
case "windows":
fmt.Println("Windows")
case "darwin":
fmt.Println("MAC operating system")
case "linux":
fmt.Println("Linux")
default:
fmt.Printf("%s.\n", os)
}
}
ตัวแปรสภาพแวดล้อม GOOS เป็นเป้าหมายระบบปฏิบัติการของโปรแกรม ที่ทำงานอยู่: darwin, freebsd, linux, และอื่นๆ ตามค่าของตัวแปร โปรแกรมจะพิมพ์เวอร์ชันของระบบปฏิบัติการ ในตัวอย่างคือ Windows
Go command-line
command-line arguments คือตัวเลือกและข้อมูลที่ส่งผ่านไปยังโปรแกรม เรามักจะส่งผ่านอาร์กิวเมนต์ไปยังโปรแกรมคอนโซล แต่บางครั้งเราก็ส่งผ่านอาร์กิวเมนต์ไปยังโปรแกรม GUI ด้วย
command-line อาร์กิวเมนต์ os.Args ค่าแรกในส่วนนี้คือชื่อของโปรแกรม ในขณะที่ os.Args[1:] เป็นค่าอาร์กิวเมนต์สำหรับโปรแกรม อาร์กิวเมนต์แต่ละรายการสามารถเข้าถึงได้ด้วย indexing operation
ตัวอย่างได้รับ command-line arguments
package main
import (
"fmt"
"os"
"reflect"
)
func main() {
prg_name := os.Args[0]
fmt.Printf("The program name is %s\n", prg_name)
names := os.Args[1:]
fmt.Println(reflect.TypeOf(names))
for _, name := range names {
fmt.Printf("Hello, %s!\n", name)
}
}
เราได้รับและพิมพ์อาร์กิวเมนต์แรกซึ่งเป็นชื่อโปรแกรม
prg_name := os.Args[0]
fmt.Printf("The program name is %s\n", prg_name)
เราได้รับข้อโต้แย้งที่ได้รับทั้งหมด
names := os.Args[1:]
เราพิมพ์ type ที่มีอาร์กิวเมนต์ (slice)
fmt.Println(reflect.TypeOf(names))
เราผ่านข้อโต้แย้งและสร้างข้อความจากแต่ละรายการ
for _, name := range names {
fmt.Printf("Hello, %s!\n", name)
}
เราสร้างโปรแกรมและเรียกใช้ โดยส่ง 3 ชื่อบนโปรแกรม command line
ทดสอบการทำงานโดย ใช้คำสั่ง go build read_args.go หลังจากสั่งคำสั่งนี้ สิ่งที่เราจะได้ก็คือ ตัว Application ชื่อ read_args ที่ถูก Execute ออกมา พร้อมนำไปใช้งาน
go build read_args.go
ส่ง 3 ชื่อบนโปรแกรม command line
./read_args Jan Peter Lucia
ฟังก์ชั่น (Go function)
ฟังก์ชันคือการแมปของพารามิเตอร์อินพุต 0 หรือมากกว่ากับพารามิเตอร์เอาต์พุต 0 หรือมากกว่า ฟังก์ชั่น Go เป็น first-class citizens สามารถกำหนดฟังก์ชันให้กับตัวแปร ส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชัน หรือส่งคืนจากฟังก์ชันได้
ฟังก์ชั่นใน Go ถูกสร้างขึ้นด้วยคำหลัก func เราใช้คำหลัก return เพื่อคืนค่าจากฟังก์ชัน เนื้อหาของฟังก์ชันประกอบด้วยคำสั่งที่ดำเนินการเมื่อมีการเรียกใช้ฟังก์ชัน ในการเรียกใช้ฟังก์ชัน เราระบุชื่อตามด้วยวงเล็บกลม () ฟังก์ชันอาจรับหรือไม่ใช้พารามิเตอร์ก็ได้
ในตัวอย่างโค้ด เรากำหนดฟังก์ชันที่เพิ่มค่า 2 ค่า
package main
import "fmt"
func main() {
x := 4
y := 5
z := add(x, y)
fmt.Printf("Output: %d\n", z)
}
func add(a int, b int) int {
return a + b
}
เราเรียกใช้ฟังก์ชัน add มันต้องใช้ 2 พารามิเตอร์ ค่าที่คำนวณได้ถูกส่งไปยังตัวแปร z
z := add(x, y)
เรากำหนดฟังก์ชัน add พารามิเตอร์ของฟังก์ชันถูกคั่นด้วยเครื่องหมายจุลภาค ชื่อพารามิเตอร์แต่ละตัวตามด้วยประเภทข้อมูล หลังจากพารามิเตอร์ เราจะระบุประเภทข้อมูลในการ return
คำสั่งที่ดำเนินการเมื่อมีการเรียกใช้ฟังก์ชันจะถูกวางไว้ระหว่างวงเล็บปีกกา ผลลัพธ์ของการดำเนินการเพิ่มเติมจะถูกส่งกลับไปยังผู้เรียกด้วยคำหลัก return
func add(a int, b int) int {
return a + b
}
credit : https://zetcode.com/