Biến môi trường (Environment Variables) là các cặp key-value được định nghĩa trong hệ điều hành (operating system). Các cặp key-value này có thể được truy cập bởi các ứng dụng đạng chạy trong hệ thống. Chúng ta có thể coi biến môi trường là các biến hoặc hằng số được sử dụng trong ứng dụng, ngoại trừ nó được định nghĩa bên ngoài ứng dụng và chúng có thể được truy cập bởi các ứng dụng khác

Trong bài viết này, chúng ta sẽ tìm hiểu về biến môi trường và cách sử dụng các biến môi trường trong ứng dụng Go

Sử dụng các biến môi trường

Một trong những lý do chính để chúng ta sử dụng biến môi trường là không muốn hard-code (fix cứng) những thông tin nhạy cảm trong code (ví dụ : username, password của database, key access của API, ...). Thay vào đó thì chúng ta đặt các thông tin nhạy cảm đó vào trong các biến môi trường để người khác không biết nó, cũng như giúp chúng ta có thể dễ dàng di chuyển ứng dụng từ server này sang server khác

Trước khi bắt đầu với việc sử dụng biến môi trường, chúng ta sẽ tìm hiểu một vài khái niệm cơ bản về cách hoạt động của chúng trong windows và macOS

Windows

Trong windows, chúng ta có thể sử dụng set để xem danh sách các biến môi trường hiện có

set

Nếu muốn tạo một biến môi trường mới, sử dụng set và cần chỉ định key và value cho biến môi trường đó

Ví dụ:

set MYDB_PASSWORD=123

Để truy xuất một biến môi trường, chúng ta sử dụng câu lệnh echo và tên biến môi trường sẽ được bao bởi cặp dấu %

echo %MYDB_PASSWORD%
123

macOS

Trong macOS, chúng ta sử dụng env để xem danh sách các biến môi trường hiện có. Nếu muốn thêm một biến môi trường mới, hãy sử dụng câu lệnh export và cần chỉ định key và value cho biến môi trường đó

Ví dụ:

export MYDB_PASSWORD=123

Để truy xuất một biến môi trường, chúng ta sử dụng câu lệnh echo, với tiền tố $ được đặt trước tên biến môi trường

echo MYDB_PASSWORD
123

Liệt kê tất cả các biến môi trường trong Go

Trong Go, chúng ta có thể sử dụng package os để truy cập vào các biến môi trường.

Đầu tiên, sử dụng hàm Environ để trả về tất cả các biến môi trường ở dạng key-value

package main
import (
    "fmt"
    "os"
    "strings"
)
func main() {
    for _, e := range os.Environ() {
        pair := strings.SplitN(e, "=", 2) 
        fmt.Printf("%s\n", pair[0])
    }
}

Chúng ta sẽ nhận được một kết quả tương tự như sau khi chạy

$ go run main.go
USER
__CFBundleIdentifier
COMMAND_MODE
LOGNAME
PATH
SSH_AUTH_SOCK
SHELL
HOME
__CF_USER_TEXT_ENCODING
TMPDIR
XPC_SERVICE_NAME
XPC_FLAGS
ORIGINAL_XDG_CURRENT_DESKTOP
SHLVL
PWD
OLDPWD
HOMEBREW_PREFIX
HOMEBREW_CELLAR
HOMEBREW_REPOSITORY
HOMEBREW_SHELLENV_PREFIX
MANPATH
INFOPATH
CONDA_EXE
CONDA_PYTHON_EXE
CONDA_SHLVL
CONDA_PREFIX
CONDA_DEFAULT_ENV
CONDA_PROMPT_MODIFIER
NVM_DIR
NVM_CD_FLAGS
NVM_BIN
NVM_INC
TERM_PROGRAM
TERM_PROGRAM_VERSION
LANG
COLORTERM
VSCODE_GIT_IPC_HANDLE
GIT_ASKPASS
VSCODE_GIT_ASKPASS_NODE
VSCODE_GIT_ASKPASS_MAIN
TERM
_CE_M
_CE_CONDA

Nếu bạn muốn in biến môi trường và giá trị tương ứng của nó, chỉ cần truy cập vào phần tử thứ 2

 fmt.Printf("%s: %s\n", pair[0], pair[1])

Setting and Getting Environment Variables

Trong chương trình Go, chúng ta cũng có thể tạo ra các biến môi trường và khởi tạo giá trị cho nó để có thể truy cập được ở bất cứ đâu trong ứng dụng. Để làm được điều này, sử dụng hàm Setenv và truyền key và value cho nó

err := os.Setenv("DATABASE_PWD", "123")

Hàm Setenv sẽ trả về một error nếu trong quá trình tạo biến môi trường gặp lỗi

Để truy xuất giá trị của một biến môi trường cụ thể, sử dụng Getenv

fmt.Printf("Database Password: %s\n", os.Getenv("DATABASE_PWD"))

Nếu chúng ta truy xuất một biến môi trường không tồn tại, thì giá trị trả về sẽ là 1 chuỗi rỗng

Ví dụ:

fmt.Printf("Database name: %s\n", os.Getenv("DATABASE_NAME"))

Nếu giá trị của một biến môi trường là 1 chuỗi rỗng, nó không hữu ích lắm nếu chúng ta sử dụng nó. Điều này có nghĩa là biến môi trường đó không tồn tại hoặc là giá trị của biến môi trường đó là một chuỗi rỗng

Một cách tốt hơn để xác định là sử dụng hàm LookupEnv. Hàm này trả về 2 giá trị:

  • Giá trị của biến môi trường được chỉ định
  • Giá trị boolean cho biết biến môi trường này có tồn tại hay không
if v, ok := os.LookupEnv("DATABASE_NAME"); ok {
    fmt.Printf("Database name: %s\n", v)
} else {
    fmt.Println("Key does not exists")
}

Sử dụng biến môi trường trong command line

Đôi khi chúng ta không muốn code của mình chứa các dữ liệu nhạy cảm, và cách tốt hơn là truyền chúng vào chương trình trong quá trình thực thi bằng cách sử dụng command line

$ DATABASE_NAME=mysql go run main.go
Database name: mysql

Trong ví dụ trên, chúng ta đặt biến môi trường DATABASE_NAME trước khi chạy chương trình. Nếu muốn truyền nhiều biến thì có thể làm như sau

$ DATABASE_NAME=mysql DATABASE_PWD=secret go run main.go

Load biến môi trường thì file

Một cách khác để truy xuất các biến môi trường là sử dụng file. Chúng ta có thể lưu trữ các thông tin nhạy cảm của ứng dụng vào trong file và ứng dụng có thể load các dữ liệu cần thiết từ file này. Để làm việc này, chúng ta có thể sử dụng package github.com/joho/godotenv

Đầu tiên chúng ta tạo thư mục chứa ứng dụng go

$ cd ~
$ mkdir environmentvars

Trong thư mục này thì chúng ta sẽ tạo file main.go

ackage main
import (
    "fmt"
    "log"
    "os"
    "github.com/joho/godotenv"
)
func main() {
    err := godotenv.Load(".env")
    if err != nil {
        log.Fatalf("Error loading .env file")
    }
    databasePwd := os.Getenv("MYSQL_DATABASE_PWD")
    fmt.Printf("godotenv : %s = %s \n", "Database Password", 
               databasePwd)
}

Tạo 1 tệp mới với tên là .env. Thông tin trong tệp như sau

MYSQL_DATABASE_PWD=123

Ngoài ra thì chúng ta có thể lưu trữ nhiều biến môi trường trong file .env. Ví dụ

environment_variable1=value1
environment_variable2=value2
environment_variable3=value3

Chạy câu lệnh sau trong teminal

$ cd ~/environmentvars
$ go mod init myapp      
go: creating new go.mod: module myapp
go: to add module requirements and sums:
        go mod tidy
$ go mod tidy
go: finding module for package github.com/joho/godotenv
go: found github.com/joho/godotenv in github.com/joho/godotenv v1.4.0

Câu lệnh trên sẽ download package github.com/joho/godotenv. Và khi chạy chương trình, chúng ta có kết quả như sau

$ go run main.go 
godotenv : Database Password = 123