# 1.2 $GOPATH และ workspace ## $GOPATH Go มีกรรมวิธีในการจัดการไฟล์ code ที่เป็นเอกลักษณ์ ด้วยการเพิ่มไดเร็คทอรีีที่เรียกว่า `$GOPATH` เพื่อใช้ในการเก็บ code ของ Go ทั้งหมดในเครื่อง ขอให้สังเกตุว่าเป็นคนละตัวกับค่าตัวแปร environment `$GOROOT` ซึ่งเป็นค่าที่บอกว่า Go ถูกติดตั้งไว้ที่ใดในเครื่อง โดยเราต้องกำหนดค่าให้กับ `$GOPATH` ก่อนที่จะสามารถใช้งานภาษาได้ โดยในระบบ *nix ทั้งหลายนั้น จะมีไฟล์ `.profile` อยู่ และเราต้องเพิ่มคำสั่ง export ที่อยู่ด้านล่างนี้เข้าไปในไฟล์ แนวคิดเบื้องหลัง gopath นี้เป็นเรื่องใหม่ ที่จะทำให้เราสามารถเชื่อมไปที่ code ของ Go ได้อย่างรวดเร็วและชัดเจน เริ่มตั้งแต่ Go 1.8 เป็นต้นมา ค่าของตัวแปร GOPATH จะถูกกำหนดค่าให้อัตโนมัติหากเราไม่ได้กำหนดให้เป็นอย่างอื่น โดยจะมีค่่าเป็น `$HOME/go` บนระบบ Unix และ `$USERPROFILE%/go` บน Windows บนระบบคล้าย Unix ทั้งหลาย ค่าตัวแปรควรจะถูกตั้งค่าดังนี้: export GOPATH=${HOME}/mygo บน Windows เราจำเป็นต้องสร้างตัวแปร environment GOPATH ขึ้นมา แล้วกำหนดค่าให้เป็น `c:\mygo` ( ***ค่านี้อาจมีค่าแตกต่างออกไปขึ้นอยู่กับว่า workspace อยู่ที่ไหน*** ) เป็นไปได้ที่จะมีหลาย path (workspace) ใน `$GOPATH` แต่เราต้องจำให้ได้ว่าต้องใช้ `:` (`;` สำหรับ Windows) คั่นระหว่างกลางแต่ละค่า โดยจุดนี้ `go get` จะบันทึกข้อมูลไปที่ path แรกที่ระบุใน `$GOPATH` แต่ขอแนะนำว่าไม่ควรใช้วิธีนี้ นอกจากนี้แล้วนับว่าเป็นเรื่องแย่ที่เราจะสร้างโฟลเดอร์โดยตั้งชื่อด้วยชื่อของโปรเจ็คแล้ววางไว้ใน `$GOPATH` นี่จะเป็นการทำลายทุกอย่างที่ผู้สร้างตั้งใจที่จะให้เป็นความเปลี่ยนแปลงของภาษา ด้วยเหตุผลว่าหากเราสร้างโฟลเดอร์ไว้ใน `$GOPATH` โดยตรงแล้ว เวลาที่เราจะอ้างถึง package เราจะต้องอ้างถึงโดยใช้ โดยตรง และนี่จะทำให้เกิดปัญหาขึ้นเนื่องจาก `go get` จะไม่สามารถหา package พบ ได้โปรดทำตาม convention มันมีเหตุผลที่มันถูกสร้างขึ้นมา ใน `$GOPATH` นั้นต้องประกอบด้วย 3 โฟลเดอร์ดังนี้: - `src` สำหรับเก็บไฟล์ source code ที่มีนามสกุล .go, .c, .g, .s - `pkg` สำหรับเก็บไฟล์ที่ได้จากการคอมไพล์ซึ่งจะมีนามสกุลเป็น .a - `bin` สำหรับเก็บไฟล์ประเภท executable ในหนังสือเล่มนี้ จะใช้ `mygo` เป็น path เดียวที่มีใน `$GOPATH` ## ไดเร็คทอรีที่ใช้เก็บ package ในการสร้าง source file และโฟลเดอร์ของ package เช่น `$GOPATH/src/mymath/sqrt.go` (`mymath` คือชื่อ package) ( ***ผู้เขียนใช้ชื่อ `mymath` เป็นทั้งชื่อ package และเป็นชื่อโฟลเดอร์ที่เก็บ source file ของ package***) ทุกครั้งที่สร้าง package ใหม่ เราควรสร้างโฟลเดอร์ใหม่ไว้ในไดเร็คทอรี `src` ยกเว้นโฟลเดอร์ main เนื่องจากโฟลเดอร์ `main` จะสร้างหรือไม่ก็ได้ไม่บังคับ โดยปรกติแล้วชื่อของโฟลเดอร์จะตั้งชื่อตามชื่อ package จะจะถูกเรียกใช้ และสามารถสร้างไดเร็คทอรีย่อยกี่ชั้นก็ได้ตามที่ต้องการ ยกตัวอย่างเช่น ถ้าสร้างไดเร็คทอรี่ `$GOPATH/src/github.com/astaxie/beedb` ชื่อ path ของ package ก็จะเป็น `github.com/astaxie/beedb` และชื่อ package เองก็คือชื่อไดเร็คทอรีตัวสุดท้ายของ path ซึ่งในกรณีนี้ก็คือ `beedb` รันคำสั่งดังนี้ ( ***ตอนนี้ผู้เขียนกลับมาพูดถึงตัวอย่าง*** ) cd $GOPATH/src mkdir mymath สร้างไฟล์ใหม่ชื่อ `sqrt.go` และเนื้อหาของไฟล์ดังนี้ ```Go // Source code of $GOPATH/src/mymath/sqrt.go package mymath func Sqrt(x float64) float64 { z := 0.0 for i := 0; i < 1000; i++ { z -= (z*z - x) / (2 * x) } return z } ``` ตอนนี้เราได้สร้างไดเร็คทอรีของ package และเขียน code เรียบร้อยแล้ว และขอแนะนำให้ใช้ชื่อ package เป็นชื่อเดียวกับไดเร็คทอรี และ source file ทั้งหมดของ package เก็บไว้ภายใต้ไดเร็คทอรีนี้่่ ## การคอมไพล์ package หลังจากสร้าง package ตามขั้นตอนเสร็จแล้ว เราก็ลองมาสั่งคอมไพล์ package กันดู โดยการคอมไพล์ package สามารถทำได้ 2 วิธีดังนี้: 1. ไปที่ path ในไดเร็คทอรีของ package แล้วใช้คำสั่ง `go install` 2. หรือใช้คำสั่งเหมือนด้านบน แต่ไม่ต้องใส่ชื่อไฟล์ เช่น `go install mymath` หลังจากที่คอมไพล์เสร็จเรียบร้อยแล้ว ให้เข้าไปที่โฟลเดอร์ด้วยคำสั่ง cd $GOPATH/pkg/${GOOS}_${GOARCH} // you can see the file was generated mymath.a จะเห็นว่ามีไฟล์ซึ่งมีนามสกุล `.a` อยู่ ซึ่งก็คือไฟล์่่ binary ของ package นั่นเอง แล้วเราจะเรียกใช้งานมันยังไงหละ? แน่นอนว่าเราจำเป็นต้องสร้างแอพพลิเคชั่นใหม่ขึ้นมา เพื่อเรียกใช้งาน package นี้ ให้ทำการสร้างแอพพลิเคชั่นใหม่ชื่อ `mathapp` cd $GOPATH/src mkdir mathapp cd mathapp vim main.go แล้วใส่เนื้อหาดังต่อไปนี้ลงในไฟล์ main.go ```Go //$GOPATH/src/mathapp/main.go source code. package main import ( "mymath" "fmt" ) func main() { fmt.Printf("Hello, world. Sqrt(2) = %v\n", mymath.Sqrt(2)) } ``` ในการคอมไพล์แอพพลิเคชั่น เราต้องเข้าไปอยู่ที่ไดเร็คทอรีของแอพพลิเคชั่นที่ต้องการคอมไพล์ ซึ่งในที่นี้คือ `$GOPATH/src/mathapp` แล้วจึงสั่งคำสั่ง `go install` เมื่อคอมไพล์เสร็จแล้วจะเห็นไฟล์ที่ชื่อว่า `myapp` เกิดขึ้นมาในไดเร็คทอรี `$GOPATH/bin/` โดยเราสามารถสั่งรับแอพพลิเคชั่นโดยใช้คำสั่ง `./mathapp` เมื่อทำงานเสร็จแล้วเราควรจะเห็นข้อความปรากฎที่หน้าจอ terminal ดังนี้ Hello world. Sqrt(2) = 1.414213562373095 ## การติดตั้ง package เพิ่มเติม Go มาพร้อมกับเครื่องมือที่ใช้ในการติดตั้ง package เสริม ซึ่งได้แก่คำสั่งที่เรียกว่า `go get` โดยรองรับ opensource comunity เกือบทุกที่ รวมถึง GitHub, Google Code, BitBucket และ Launchpad go get github.com/astaxie/beedb โดยสามารถใช้ `go get -u …` ในการอัพเดท package และยังสามารถติดตั้ง package ที่เป็น dependency ให้โดยอัตโนมัติด้วย ซึ่งเครื่องมือนี้จะใช้ version control ที่แตกต่างกันสำหรับแต่ละ opensource platform ยกตัวอย่างเช่น จะใช้่่ `git` สำหรับ GitHub และใช้ `hg` สำหรับ Google Code ดังนั้นเราจำเป็นที่จะต้องติดตั้งเครื่องมือ version control เหล่านี้ก่อนที่เราจะใช้ `go get` ได้ หลังจากที่รันคำสั่งที่กล่าวมาแล้ว โครงสร้างไดเร็คทอรีควรมีหน้าตาดังนี้ $GOPATH src |-github.com |-astaxie |-beedb pkg |--${GOOS}_${GOARCH} |-github.com |-astaxie |-beedb.a อันที่จริงแล้ว `go get` จะทำการ clone source code ไปเก็บไว้ที่ `$GOPATH/src` ในเครื่อง เสร็จแล้วให้สั่ง `go install` จะทำให้เราสามารถใช้ package ซึ่งมาจากที่อื่น (remote packages) ได้ในแบบเดียวกับที่เราใช้ package ที่อยู่ในเครื่องของเราเอง ```Go import "github.com/astaxie/beedb" ``` ## โครงสร้างไดเร็คทอรี่แบบสมบูรณ์ หากเราทำตามคำสั่งที่กล่าวมาแล้วทั้งหมด โครงสร้างไดเร็คทอรีในเครื่องของเราควรจะมีลักษณะดังนี้ bin/ mathapp pkg/ ${GOOS}_${GOARCH}, such as darwin_amd64, linux_amd64 mymath.a github.com/ astaxie/ beedb.a src/ mathapp main.go mymath/ sqrt.go github.com/ astaxie/ beedb/ beedb.go util.go ตอนนี้เราจะเห็นโครงสร้างได้อย่างชัดเจนว่า `bin` จะเป็นที่อยู่ของไฟล์ executable ส่วน `pkg` จะเป็นที่อยู่ของไฟล์ที่ได้จากการคอมไพล์ และ `src` คือส่วนที่เก็บ source file ของ package นั่นเอง (รูปแบบของตัวแปร environment บน Windows คือ `%GOPATH%` แต่ว่าอย่างไรก็ตาม หนังสือเล่มนี้จะเป็นสไตล์ของ Unix ดังนี้ผู้ใช้งาน Windows จึงต้องแก้ให้ถูกต้องด้วยตัวเอง) ## Links - [Directory](preface.md) - บทก่อนหน้า: [การติดตั้ง](01.1.md) - บทถัดไป: [คำสั่งของ Go](01.3.md)