บันทึกการเรียน Golang วันที่ 4 - ว่าด้วยเรื่องของ environment variables

Go Aug 30, 2023

วันนี้ได้เรียนรู้และรู้จักกับ Environment Variables ใน Go ว่ามีวิธีการเข้าถึงพวก variables ยังไงได้บ้าง ปกติเวลาที่เขียน Node.js ถ้าไม่ได้กำหนด system variables ก็มักจะใส่ไปพร้อมกับตอน execute command และอีกวิธีคือ ใช้ไฟล์ .env ร่วมกับ 3rd party library อย่าง dotenv นั่นเอง

สำหรับการฝึกเขียน Golang วันนี้ได้ลองเรียก HTTP Request ผ่านตัว Golang และมีการใช้ credentials ทำให้เราไม่ควรใส่ค่าไว้ใน Source Code ก็เลยมาลองดูว่า มีวิธีไหนบ้าง ที่จะทำงานคล้ายๆ กับ .env ของ Node.js + dotenv

ลองสร้างโปรเจ็คขึ้นมา และ initial module

mkdir learn-go-day-4
cd learn-go-day-4

go mod init goenv

แบบที่ 1 - Go os.Getenv

วิธีแรก คือใช้ os ที่เป็น standard library ครับ สร้างไฟล์ขึ้นมาง่ายๆ main.go

package main

import (
  "fmt"
  "os"
)

func main() {
  environment := os.Getenv("GO_ENV")

  fmt.Println("GO_ENV: ", environment)
}

เวลารัน command ก็ใส่ env ไปพร้อมๆกัน แบบเดียวกับรัน Node.js

GO_ENV=staging go run go-get.go

// ผลลัพธ์
// GO_ENV: staging

วิธีที่ 2 - ใช้ godotenv

วิธีนี้จะใช้ library ชื่อ godotenv ครับ การใช้งานก็เหมือนกับตัว dotenv ที่เป็นเวอร์ชั่น Node.js คือโหลดจากไฟล์ .env ซึ่งจริงๆ เราสามารถตั้งชื่ออะไรก็ได้ รวมถึงรองรับ format YAML ด้วยเช่นกัน

GitHub - joho/godotenv: A Go port of Ruby’s dotenv library (Loads environment variables from .env files)
A Go port of Ruby’s dotenv library (Loads environment variables from .env files) - GitHub - joho/godotenv: A Go port of Ruby’s dotenv library (Loads environment variables from .env files)

ทำการเพิ่ม library

go get github.com/joho/godotenv

สร้างไฟล์ .env ไว้ที่ root ของโปรเจ็ค ข้างในสมมติ ผมมีแบบนี้อยู่

SECRET_KEY=this_is_super_secret
GO_ENV=development

ขั้นแรก ทำการโหลดไฟล์ .env ขึ้นมาก่อน

err := godotenv.Load()

if err != nil {
  log.Fatal("Error loading env")
}

โดยถ้าใครอยากให้มันโหลดไฟล์ นอกเหนือจาก `.env ก็ระบุชื่อไฟล์ไปเลย เช่น

godotenv.Load("myEnvFile")

ซึ่งเราให้มัน autoload ได้ด้วยแบบนี้ ด้านบนลบทิ้งได้เลย สำหรับสายขี้เกียจ และไฟล์ default ก็เป็นชื่อ .env อยู่แล้ว ใช้แบบนี้แทนได้

import _ "github.com/joho/godotenv/autoload"

ส่วนนี้ จริงๆ มันก็เหมือนกับเรา โหลด variables ไปพร้อมกับ run คำสั่ง ซึ่งมันมีค่าเท่ากับ

SECRET_KEY=xxx GO_ENV=xxx go run <filename>

ส่วน function ที่ใช้ในการ get env ก็ใช้ตัว standard library ได้เลย

  environment := os.Getenv("GO_ENV")
  secretKey := os.Getenv("SECRET_KEY")

  fmt.Println("GO_ENV: ", environment)
  fmt.Println("SECRET_KEY: ", secretKey)

ส่วนการโหลดไฟล์ YAML ก็ทำได้เช่นกัน (แต่ผมยังติดปัญหา ว่ามันไม่สามารถ parse กรณีที่เราใช้เป็น Nested Object หรือเป็น list items แฮะ)

ส่วนอีก library ที่เห็นว่าคนใช้เยอะ ก็คือ Viper ส่วนตัวยังไม่ได้ลองใช้งานนะครับ เพราะตอนนี้ใช้ godotenv ก็ตอบโจทย์ที่โหลด environment variables พวก api key, secret key แล้ว ยังไม่ได้ทำ config ให้มี structure ที่ซับซ้อน ก็เลยยังไม่ได้ใช้ Viper ครับ

GitHub - spf13/viper: Go configuration with fangs
Go configuration with fangs. Contribute to spf13/viper development by creating an account on GitHub.

ซึ่งจากที่ดูใน Github ตัว Viper รองรับทั้ง .env ทั้ง YAML / JSON และไฟล์หลากหลาย แต่ผมเห็นตัวอย่างโค๊ดแล้ว มันดูจะเยอะเกินไป เหมาะกับโปรเจ็ค หรือ config ไฟล์ที่ซ้ำซ้อนมากกว่า

Happy Coding ❤️

Tags

Chai Phonbopit

เป็น Web Dev ทำงานมา 10 ปีหน่อยๆ ด้วยภาษา JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจ Web3, Crypto และ Blockchain เขียนบล็อกที่ https://devahoy.com