จากบทความ Using Go Modules จาก website หลักของภาษา Go
ทำการอธิบายการใช้งาน Go Module
ซึ่งใน Go version 1.13 เป็นต้นไปจะเป็นค่า default สำหรับการพัฒนา
ดังนั้นควรทำการซึกษาและใช้งานกันได้แล้ว
ประกอบไปด้วย
- การสร้าง module ใหม่
- การเพิ่ม dependency เข้ามาใหม่
- การ upgrade dependency ต่าง ๆ
- การเพิ่ม dependency เข้ามายัง major version
- การ upgrade dependency เข้ามายัง major version
- การลบ dependency ที่ไม่ได้ใช้ออกไป
โดยจะทำการสรุปไว้ 3 เรื่องพอคือ
- การสร้าง module ใหม่
- การเพิ่ม dependency เข้ามาใหม่
- การลบ dependency ที่ไม่ได้ใช้ออกไป
Module นั้นคือกลุ่มของ Go package ที่ถูกจัดเก็บในรูปแบบของ tree
ซึ่งถูกกำหนดอยู่ในไฟล์ชื่อว่า go.mod โดยที่ไฟล์ go.mod
จะอยู่ที่ root ของ module นั่นเอง ในไฟล์นี้จะใช้จัดเก็บ
- Path ของ module
- Dependency ต่าง ๆ ที่ต้องการใช้งาน รวมไปถึงตัวอื่น ๆ ที่ต้องการใช้งาน
- Dependency แต่ละตัวที่ใช้งานต้องกำหนด version แบบ Semantic versioning ด้วย
มาลองทำตามบทความกัน ได้ความรู้ดีมากเลย
เหมาะมาก ๆ สำหรับคนเริ่มต้นศึกษาและใช้งานใหม่ ๆ
1. การสร้าง module ใหม่
ให้ทำการสร้าง directory ว่าง ๆ นอก $GOPATH/src นะ
จากนั้นทำการสร้างไฟล์ hello.go มีเพียง function เดียวคือ Hello()
และส่งค่า Hello, world. กลับมา ดังนี้
[gist id="4cf4a55a5af940e9283513b8edd70d28" file="hello.go"]
ต่อมาเขียนชุดการทดสอบ
เห็นไหมว่า แม้แต่บทความสำหรับผู้เริ่มต้นก็เขียนชุดการทดสอบแล้วนะ
ดังนั้นใครไม่เขียนนี่จัดว่าบาปเลยนะ !!
[gist id="4cf4a55a5af940e9283513b8edd70d28" file="hello_test.go"]
ทำการ run ชุดการทดสอบง่าย ๆ
[code] $go test PASS okทำการแสดงผลของการ run ชุดการทดสอบ
ของระบบงานที่อยู่นอก $GOPATH และไม่อยู่ใน module ใด ๆ เลย
ดังนั้นได้เวลามาสร้าง Module แรกกันแล้ว
ชื่อ module คือ example.com/hello ด้วยการใช้คำสั่งดังนี้
สังเกตไหมว่า สิ่งที่เปลี่ยนไปคือ
จะแสดงว่ากำลังทดสอบใน module ของเราที่เพิ่มสร้างขึ้นมาใหม่นั่นเอง
เพียงเท่านี้ก็สร้าง Module ได้แล้ว
จากนั้นลองไปเปิดไฟล์ go.mod ดูจะเห็นดังนี้
[code] module example.com/hello go 1.12 [/code]ต้องจำไว้ว่าไฟล์ go.mod จะอยู่ที่ root directory ของ Module นั้น ๆ เท่านั้น
ถ้าต้องการสร้าง package ย่อย ๆ ก็ให้สร้าง subdirectory ลงไปเรื่อย ๆ
แล้ว Go จะวิ่งไปหาให้เองแบบอัตโนมัติ
ยกตัวอย่างเช่นสร้าง directory ย่อยชื่อว่า world
นั่นคือชื่อ package จากนั้นถ้าต้องการเรียกใช้ ให้ทำการ import example.com/hello/word
[gist id="4cf4a55a5af940e9283513b8edd70d28" file="hello_test2.go"]
ทำการ run ชุดการทดสอบด้วยคำสั่ง
[code] $go test ./.. PASS ok example.com/hello ok example.com/hello/world [/code]ดู code เพิ่มเติมได้จาก Github::Up1
2. การเพิ่ม dependency เข้ามาใหม่
ในการเพิ่ม depedency นี่เองที่ช่วยทำให้นักพัฒนาง่ายและสะดวกขึ้น
มันเปลี่ยนวิธีการคิดของนักพัฒนาไปเลย
นั่นคือ เพียงแค่ทำการ import dependency ใน code ไป
แล้ว Go module จะทำการ download และ update dependency ที่ต้องใช้งานให้เอง
ทั้ง direct และ indirect dependency
โดยที่จะไป download version ล่าสุดที่เป็นไปตาม Semantic versioning นั่นเอง
แน่นอนว่า ต้องไปแก้ไขไฟล์ go.mod ให้เองอีกด้วย
มาลองดูกัน
[gist id="4cf4a55a5af940e9283513b8edd70d28" file="hello2.go"]
จากนั้นทำการทดสอบได้ดังนี้
[code] $go test go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c PASS ok example.com/hello 0.007s [/code]แต่ถ้า run ซ้ำอีกครั้ง จะไม่ donwload อีกแล้ว
เพราะว่า ทำการเก็บ caching ไว้ให้แล้ว
คำถามคือ แล้ว caching file อยู่ที่ไหน ?
คำตอบคือ ลองใช้คำสั่งนี้ดู จะทำการสิ่งที่เราต้องการออกมาทั้งหมด
เมื่อเปิดดูไฟล์ go.mod จะมีการเพิ่ม dependency ที่ใส่ใน code เข้ามา
[code] module example.com/hello go 1.12 require rsc.io/quote v1.5.2 [/code]ยังไม่พอนะ ยังสร้างไฟล์ go.sum เข้ามา
สำหรับเก็บ checksum ของสิ่งที่ download มาไว้
เพื่อทำให้แน่ใจว่า ต่อไปจะทำการ download dependency ตัวเดิม
ไม่ผิดตัวนั่นเอง
ถ้าอยากรู้ว่า Module ของเรามี dependency อะไรบ้าง ?
ให้ใช้คำสั่ง
3. การลบ dependency ที่ไม่ได้ใช้ออกไป
ง่ายมาก ๆ คือ run คำสั่ง $go mod tidy ก็จบแล้ว
ลองใช้งานกันครับ
ซึ่ง Go module มีมาตั้งแต่ Go version 1.11 แล้วนะ
โดยในบทความสรุป workflow การใช้งาน ไว้ดังนี้
- go mod init สำหรับการสร้าง module
- go build และ go test สำหรับการ build และ ทดสอบ โดยจะอ่านค่าจากไฟล์ go.mod
- go list -m all ดู dependency ต่าง ๆ ที่ใช้งานใน module
- go get สำหรับเปลี่ยน version ของ dependency
- go mod tidy สำหรับลบ dependency ที่ไม่ได้ใช้ออกไปจาก module