Skip to main content

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 แบบ คือ

  1. Direct Import
    - Single
    - Multiple one-by-one
  2. 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

image.png

  1. Name: ชื่อของฟังก์ชัน ควรตั้งเป็นแบบ camelCase / CamelCase.
  2. Arguments: ฟังก์ชันสามารถรับหรือไม่รับ arguments ก็ได้ สำหรับ arguments ที่อยู่ติดกันตั้งแต่ 2 รายการขึ้นไปที่มีชนิดตัวแปรเดียวกัน สามารถกำหนดชนิดตัวแปรที่ด้านหลังของ argument สุดท้ายได้ (เช่น "String" ในตัวอย่าง)
  3. Return Types: ฟังก์ชันสามารถคืนค่าหรือไม่ก็ได้ หากส่งคืนค่ามากกว่าหนึ่งค่า จะต้องใส่ชนิดของค่าที่จะคืนกลับไปทั้งหมดในวงเล็บ
  4. 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")
}