การจัดการ Go package
Go package คืออะไร ?
Go package คือ วิธีการจัดการและการ reuse code ใน go โดย
- ประกาศผ่าน keyword
package
ที่ตำแหน่งบนสุดของไฟล์ - ถ้า
package
คือ main (ไฟล์หลักของ go) = ต้องมี main function เพื่อเป็น จุดเริ่มต้นของ function - ไฟล์ go อื่นๆ สามารถ import ผ่าน package ที่ประกาศได้
ประโยชน์ของการใช้ Go Package
- ทำให้ code ดูเป็นระเบียบ และสามารถ reuse code ได้ง่าย
- สามารถสร้างเป็น package เพื่อให้คนอื่นสามารถใช้ source code เราได้ (ผ่านคำสั่ง
go get
ที่เราพึ่งทำไปเมื่อกี้ )
ก่อนไป Go package มารู้จักกับ function ก่อน
Function คือ concept ของ programming ในการรวมชุดคำสั่งเอาไว้เป็นคำสั่งใหม่คำสั่งเดียว เพื่อให้สามารถ reuse การใช้งานได้
เช่น สมมุติว่า เราต้องการเก็บชุดคำสั่งที่แสดงคำว่า "Hello World" เอาไว้ โดยเราสามารถเรียกใช้คำสั่งนี้ในอนาคตได้
- เราจึงทำการสร้าง function โดยทำการห่อคำสั่งของ "Hello World" เอาไว้ (สมมุติตั้งชื่อว่า
sayHello
) - ใน function
main()
เราก็จะสามารถเรียกใช้คำสั่งsayHello()
เพื่อเรียกใช้คำสั่งการ print แสดงผลออกมาได้
package main
import (
"fmt"
)
func sayHello() {
fmt.Println("Hello World")
}
func main() {
sayHello()
sayHello()
sayHello()
}
ก็จะได้ผลลัพธ์ sayHello()
ออกมาได้
step ต่อไป เดี๋ยวเราจะลองสร้าง function จากไฟล์อื่นและทำการ import เข้ามาบ้าง
ตัวอย่างการประกาศ Go package
- กลับมาที่ Hello World เรามีการประกาศ
package main
ซึ่งเป็นจุดเริ่มต้นของ package main
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}
เราจะลองสมมุติว่าเราจะย้าย Hello World ไปเป็น Package แทน และตั้งชื่อ package ว่า mikelopster โดยเราจะลองสร้าง structure แบบนี้กัน โดย
- เราจะสร้าง folder
mike
- ใน folder
mike
เราจะตั้งชื่อ package name ชื่อmikelopster
- จะสร้างตาม structure ด้านล่างนี้
├── go.mod
├── go.sum
├── main.go
└── mike
├── mikelopster.go
└── test.go
โดยทั้ง 2 files นั้นเราจะทำการสร้าง function สำหรับการแสดงข้อความบน console ออกมา
ที่ mikelopster.go
package mikelopster
import "fmt"
func SayMikelopster() {
fmt.Println("Hello mikelopster")
}
ที่ test.go
package mikelopster
import "fmt"
func SayTest() {
fmt.Println("Hello Test")
}
จากนั้นที่ main.go
ทำการเรียกใช้ 2 functions นี้โดย
- import folder package เข้ามา
- เรียกใช้คำสั่งผ่านชื่อ package ตามด้วย ชื่อ function
packageName.functionName()
ex.mikelopster.SayHello()
package main
import (
"github.com/mikelopster/go-example/mike" // เป็นชื่อ package เดียวกับที่ init ตอน Go module
)
func main() {
mikelopster.SayMikelopster()
mikelopster.SayTest()
}
แล้วลอง go run main.go
ก็จะได้ผลลัพธ์ออกมา
private function และ public function
ทีนี้เราจะลองมาเปลี่ยนอะไรกันสักเล็กน้อย
- ที่
mike/test.go
เราลองเปลี่ยนชื่อจากSayTest()
เป็นsayTest()
package mikelopster
import "fmt"
func sayTest() {
fmt.Println("Hello Test")
}
เมื่อลองกลับมาดูที่ main.go จะพบว่าเกิด error บางอย่างเกิดขึ้น
-
Error ท ี่เกิดขึ้น เกิดจากการที่ Go นั้นมองไม่เห็น function
sayTest()
ที่อยู่ในmike/test.go
-
เนื่องจาก Convension (ข้อตกลง) ของ Go กำหนดไว้ว่า
- function ที่ขึ้นต้นด้วยตัวพิมพ์เล็ก = private function (ที่เรียกใช้จากภายใน package เดียวกันได้เท่านั้น)
- function ที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่ = public function (ที่เรียกใช้จากภายในหรือภายนอกก็ได้)
-
ย้อนกลับไปดูเคสตัวอย่างของ
sayHello()
ใน main.go จะสังเกตว่าสามารถเรียกใช้งาน function ได้เนื่องจากอยู่ใน package เดียวกัน
กลับกัน หากเรานำ sayTest()
ไปเรียกใช้งานจากไฟล์ mike/mikelopster.go
package mikelopster
import "fmt"
func SayMikelopster() {
fmt.Println("Hello mikelopster")
sayTest()
}
แล้วให้ที่ main.go
เรียกใช้เพียง SayMikelopster()
package main
import (
"github.com/mikelopster/go-example/mike"
)
func main() {
mikelopster.SayMikelopster()
}
จะสามารถเรียกใช้งานออกมาได้
Note สำหรับเรื่องของ package
- go ไม่มี concept class ทุกอย่างจัดการผ่าน function และ package
- ใน 1 folder สามารถมีได้เพียง package เดียวเท่านั้น (หากตั้งชื่อ package ต่างกัน ใน folder เดียวกัน = จะเกิด error ออกมา)
- go มี folder ชื่อ internal ในการจัดการการมองเห็นได้ เช่น
- หากเรามี library เพิ่มเติมเป็นแบบนี้ เช่นมี folder
internal/lopster
ที่เป็น packagelopster
├── go.mod
├── go.sum
├── main.go
└── mike
├── internal
│ └── lopster
│ └── lopster.go
├── mikelopster.go
└── test.go
main.go
จะ- สามารถเรียกใช้ package ของ
mikelopster
ได้ (ใน foldermike
) - แต่ ไม่สามารถ เรียกใช้ pacakge
lopster
ที่อยุ่ใน internal ได้ จะเกิดเป็น error (แบบภาพนี้ขึ้นมา)
- สามารถเรียกใช้ package ของ
- แต่ถ้าเป็นที่
mikelopster.go
(ที่อยู่ level เดียวกันกับ internal) จะสามารถเรียกใช้ packagelopster
ได้ (เนื่องจากเป็น internal ของ packagemikelopster
)
และนี่คือพื้นฐานเริ่มต้นทั้งหมดของ Go สำหรับการ run พื้นฐานเบื้องต้น
Session ต่อไป เราจะมาลอง Basic programming ของ Go กัน