Basic Syntax
Golang
ไฟล์ Go ประกอบด้วยส่วนต่างๆ ต่อไปนี้:
1. การประกาศแพ็คเกจ
2. การนำเข้าแพ็คเกจ (import)
3. ฟังก์ชั่น
4. คำสั่งและการแสดงออก
เช่น
package main
import ("fmt")
func main() {
fmt.Println("Hello GDSC!")
}
Package
Package คือที่เก็บฟังก์ชัน ซึ่งหนึ่งแพ็คเกจสามารถเก็บได้หลายไฟล์ และสามารถตั้งชื่อไฟล์ได้อย่างอิสระ
Import
Import คือการนำเข้า Package จากข้างนอกเข้ามาใช้ในไฟล์ Go ที่เราเขียนอยู่
Example:
import "fmt" --------------------------------> fmt is the name of a package
import "os" ---------------------------------> os is the name of a package
import "github.com/gopherguides/greet" ------> this is the path of the package
Import สามารถเรียกใช้ได้ 2 แบบ คือ
- Direct Import
- Single
- Multiple one-by-one - Grouped Import
Example:
// Direct import:
// Single:
import "fmt"
// Multiple one-by-one:
import "fmt"
import "math"
// Grouped import:
import(
"fmt"
"math"
)
Variables
Go เป็นภาษาที่ประกาศชนิดของตัวแปรไว้อย่างชัดเจน (Static-Type Language) หมายความว่าคุณต้องประกาศชนิดตัวแปรเมื่อคุณประกาศตัวแปร และไม่สามารถเปลี่ยนแปลงชนิดได้อีก จุดนี้ทำให้ Golang ทำงานได้รวดเร็ว เนื่องจาก compiler ไม่จำเป็นต้องระบุชนิดตัวแปรในขณะ runtime
package main
import "fmt"
const globalConstant = 2.72
const ExportedGlobalConstant = 3.14
func main() {
var first string
first = "This is first string"
var second = "This is second string"
third := "This is third string"
fmt.Println(first, second, third)
}
การประกาศตัวแปร มี 3 วิธี ดังนี้
- first การประกาศโดยระบุชนิดตัวแปรด้วยตนเอง
- second และ third คือ การประกาศแบบไม่ระบุชนิดตัวแปรด้วยตนเอง แต่ใช้คำสั่งหลังเครื่องหมายเท่ากับกำหนดชนิดตัวแปรแทน
- third จะต้องมีเครื่องหมาย colon (:) เพื่อประกาศตัวแปร หากไม่มีเครื่องหมายทวิภาค compiler จะส่ง error หากคุณยังไม่เคยประกาศตัวแปรมาก่อน
Variables type
package main
import "fmt"
func main() {
a := 1 // var a int
b := 3.14 // var b float
c := "hi" // var c string
d := true // var d bool
fmt.Println(a, b, c, d)
e := []int{1, 2, 3} // slice
e = append(e, 4)
fmt.Println(e, len(e), e[0], e[1:3], e[1:], e[:2])
f := make(map[string]int) // map
f["one"] = 1
f["two"] = 2
fmt.Println(f, len(f), f["one"], f["three"])
}
Golang ก็เหมือนกับภาษาอื่นๆ ที่มีชนิดของตัวแปรเป็น int, float, string และ boolean ซึ่งเป็น primitive data types
Struct
Struct คือชนิดของข้อมูลอีกรูปแบบหนึ่ง ซึ่งมีความคล้ายกับ Object โดยผู้เขียนสามารถใส่ข้อมูล (field) เข้าไป และกำหนดชนิดของ field นั้น ๆ ได้
แต่ละ field สามารถส่งออกได้โดยใช้กฎเดียวกันกับตัวแปรส่วนกลาง คือการใช้อักษรตัวแรกของฟิลด์เป็นตัวพิมพ์ใหญ่ ซึ่งหมายความว่าจากตัวอย่างด้านล่าง filed Name และ Age สามารถเข้าถึงได้โดยแพ็คเกจอื่น ๆ ในขณะที่ isAdmin ไม่สามารถเข้าถึงได้
Field สามารถกำหนดแท็กเพื่อบอกข้อมูลของ field นั้นๆ เช่น (`json:"name"`) เป็นข้อมูล meta (ข้อมูลที่ใช้อธิบายรายละเอียดของข้อมูล) สำหรับ library บาง library เช่น JSON libraries (https://golang.org/pkg/encoding/json/) ที่ใช้ "แท็ก" เพื่อเปลี่ยนจาก map ไปเป็น JSON หรือ จาก JSON เป็น map
package main
import "fmt"
type Person struct{
Name string `json:"name"`
Age int `json:"age"`
isAdmin bool
}
func main() {
p := Person{
Name: "Mike",
Age: 16,
isAdmin: false,
}
fmt.Println(p, p.Name, p.Age, p.isAdmin)
}
Type Conversion
package main
import (
"fmt"
"strconv"
"reflect"
)
func main() {
a := 3.14
b := int(a)
fmt.Println(b, reflect.TypeOf(b))
c := "12.34"
d, _ := strconv.ParseFloat(c, 64)
fmt.Println(d, reflect.TypeOf(d))
e := false
f := fmt.Sprint(e)
fmt.Println(f, reflect.TypeOf(f))
}
Control Flow Statements
Conditions
package main
import "fmt"
func main() {
// if, else
a := 5
if a > 3 {
a = a - 3
} else if a == 3 {
a = 0
} else {
a = a + 3
}
fmt.Println(a)
// switch, case
b := "NO"
switch b {
case "YES":
b = "Y"
case "NO":
b = "N"
default:
b = "X"
}
fmt.Println(b)
}
Loop
package main
import "fmt"
func main() {
// for
c := 3
for i := 0; i < c; i++ {
fmt.Print(i, " ")
}
fmt.Println()
// replace while with for
for c > 0 {
fmt.Print(c, " ")
c--
}
fmt.Println()
// for with range
d := []int{0, 1, 1, 2, 3, 5, 8}
for _, i := range d {
fmt.Print(i, " ")
}
fmt.Println()
}
Defer
คำสั่ง "defer" เป็นคำสั่งพิเศษใน Go คุณสามารถเรียกใช้ฟังก์ชันใด ๆ หลังจากคำสั่งเลื่อนผ่านไป ฟังก์ชั่นจะถูกเก็บไว้ใน stack และจะถูกเรียกใช้หลังจากที่ฟังก์ชัน return ดังที่คุณเห็นในตัวอย่าง มีการกลับลำดับของการเรียกใช้ฟังก์ชัน
package main
import "fmt"
func main() {
f()
}
func f() (int, error) {
defer fmt.Println("DEFER 1")
defer fmt.Println("DEFER 2")
defer fmt.Println("DEFER 3")
fmt.Println("BODY")
return fmt.Println("RETURN")
}
Functions
Function components
Go function มีโครงสร้าง 4 ส่วนดังนี้:
- Name: ชื่อของฟังก์ชัน ควรตั้งเป็นแบบ camelCase / CamelCase.
- Arguments: ฟังก์ชันสามารถรับหรือไม่รับ arguments ก็ได้ สำหรับ arguments ที่อยู่ติดกันตั้งแต่ 2 รายการขึ้นไปที่มีชนิดตัวแปรเดียวกัน สามารถกำหนดชนิดตัวแปรที่ด้านหลังของ argument สุดท้ายได้ (เช่น "String" ในตัวอย่าง)
- Return Types: ฟังก์ชันสามารถคืนค่าหรือไม่ก็ได้ หากส่งคืนค่ามากกว่าหนึ่งค่า จะต้องใส่ชนิดของค่าที่จะคืนกลับไปทั้งหมดในวงเล็บ
- Body: การทำงานของฟังก์ชัน
Name Return Values
เราสามารถตั้งชื่อตัวแปรที่เราจะ return ค่าออกไปได้ โดยที่ไม่ต้องใส่ตัวแปรนั้นไว้ในบรรทัดเดียวกับ return
Example:
package main
import "fmt"
func main() {
fmt.Println(threeTimes("Thank You GDSC"))
}
func threeTimes(msg string) (tMsg string) {
tMsg = msg + ", " + msg + ", " + msg
return
}
Exported / Unexported Functions
จากตัวอย่างด้านล่างจะเห็นว่า Sum เป็น exported function เพราะว่าชื่อฟังก์ชันตัวแรกเป็นตัวพิมพ์ใหญ่ แต่ factorial เป็น unexported function
package main
import "fmt"
func main() {
s := Sum(10)
f := factorial(10)
fmt.Println(s, f)
}
func Sum(n int) int { // exported function
sum := 0
for i := 1; i <= n; i++ {
sum += i
}
return sum
}
func factorial(n int) int { // unexported function
fac := 1
for i := 1; i <= n; i++ {
fac *= 1
}
return fac
}
Anonymous Functions
คือฟังก์ชันที่ไม่มีชื่อ และถูกเรียกใช้เลยผ่านการประกาศตัวแปร
package main
import "fmt"
func main() {
a := 1
b := 1
c := func(x int) int {
b *= 2
return x * 2
}(a)
fmt.Println(a, b, c)
}
func mainAnother() {
myFunc := func(x int) int {
return x * x
}
fmt.Println(myFunc(2), myFunc(3))
}
Blank Identifiers (_)
คือตัวแปรที่ไม่ถูกนำมาใช้ และค่าของ blank identifier จะไม่ถูกอ่าน
ประโยชน์ของ blank identifier คือ ถ้าประกาศตัวแปรมาหลายตัว แต่ไม่ได้ถูกใช้ครบทุกตัวจะ error ทำให้มีการใช้ blank identifier แทน เพื่อให้ compiler มองข้ามตัวแปรนั้นที่ไม่ได้ถูกนำมาใช้
package main
import "fmt"
func main() {
x, _ := evenOnly(10)
fmt.Println(x)
}
func evenOnly(n int) (int, error) {
if n%2 == 0 {
return n / 2, nil
}
return 0, fmt.Errorf("not even")
}
No Comments