Tạo variable (biến) trong Go

Go có 2 cách để khai báo và khởi tạo giá trị cho variable:

var x int // declare
x = 42 // init

có thể viết gọn lại

var x int = 42

Hoặc cú pháp ngắn "short declaration":

x := 42

Short declaration rules

Short declaration := ngắn hơn, được ưa chuộng, nhưng cũng kèm theo không ít chú ý mà ít ai để ý.

package main
import (
    "fmt"
    "os"
)
func main() {
    i, err := os.Open("/etc/passwd")
    i, err := os.Open("/etc/passwd")
    fmt.Printf("i %v err %v\n", i, err)
}

Code này không compile với error: no new variables on left side of :=, bên trái := luôn phải có variable mới. Code này compile ok:

func main() {
    i, err := os.Open("/etc/passwd")
    f, err := os.Open("/etc/passwd")
    fmt.Printf("i %v f %v err %v\n", i, f, err)
}

ở đây có var f mới, còn var err cũ được gán cho giá trị mới. Bằng chứng err cũ có thể test:

func main() {
    i, _ := os.Open("/etc/passwd")
    var err int = 42
    f, err := os.Open("/etc/passwd")
    fmt.Printf("i %v f %v err %v\n", i, f, err)
}

không compile với error: cannot use os.Open("/etc/passwd") (value of type error) as int value in assignment, err cũ có kiểu int, nên không thể gán giá trị kiểu error.

Đoạn code sau rất phổ biến trong lập trình web, tạo 1 global var DB client:

var db *gorp.DbMap

//Init ...
func Init() {
    dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable", os.Getenv("DB_USER"), os.Getenv("DB_PASS"), os.Getenv("DB_NAME"))
    db, err := ConnectDB(dbinfo)
    if err != nil {
        log.Fatal(err)
    }

err là var mới, còn db là var mới hay var cũ được gán giá trị?

Theo những ví dụ trên, có thể mong chờ db là var cũ được gán cho giá trị. Nhưng theo effective go:

In a := declaration a variable v may appear even if it has already been declared, provided: if v is already declared in an outer scope, the declaration will create a new variable.

db trong Init là var db mới, shadow (che mất) var db bên ngoài, db bên ngoài vẫn là nil. Để fix bug này, không dùng := mà viết:

    var err error
    db, err = ConnectDB(dbinfo)

Kết luận

Go vốn dài dòng, mà chỗ ngắn cũng toàn chú ý, cộng đồng mạng tạo hẳn 6 luật để dùng := https://stackoverflow.com/questions/17891226/difference-between-and-operators-in-go/45654233#45654233

Go thật đơn giản, ha!

Hết.

HVN at http://pymi.vn and https://www.familug.org.

Ủng hộ tác giả 🍺



Published

Category

frontpage

Tags

Contact