- vừa được xem lúc

Handling Error trong Golang

0 0 30

Người đăng: Nguyễn Xuân Quang

Theo Viblo Asia

image.png Go không có phương thức try/catch như thông thường để xử lý lỗi, thay vào đó lỗi sẽ được trả về như một giá trị.

Chúng ta đều hiểu rằng lỗi là khi có gì đó bất thưởng xảy ra trong trường trình, nhưng trong Go thì lỗi mang một ý nghĩa khác. Lỗi với Go chỉ là một giá trị hàm có thể trả về nếu có điều gì đó không mong đợi xảy ra.

error được tích hợp sẵn trong Go với giá trị mặc định là nil. Có một cách để xử lý lỗi là trả nó về như giá trị cuối cùng của hàm gọi và kiểm tra xem nó có nil hay không.

val, err := abcFunction( args... );
if err != nil { // Xử lý lỗi
} else { // Thành công
}

error

Cùng tìm hiểu sau hơn về kiểu dữ liệu error ta có: đây là một kiểu tích hợp sẵn nhưng thực tế nó là một interface có sẵn sử dụng ở mọi nơi trong chương trình Go và nó thực thi phương thức Error() trả về một thông báo lỗi dạng string.

tpye error interface{ Error() string
}

Do đó chúng ta có thể định nghĩa các kiểu dữ liệu lỗi bằng cách thực thi cho error interface. Ví dụ:

package main import "fmt" // Tạo struct
type MyError struct{} // struct thực thi phương thức `Error`
func (myErr *MyError) Error() string { return "Something unexpected happend!"
} func main() { // tạo error myErr := &MyError{} // in ra thông báo lỗi fmt.Println(myErr)
}

Trong ví dụ trên, ta đã tạo struct MyError, cung cấp thực thi code cho phương thức Error. Phương thức này trả về một string. Do đó struct MyError đã thực thi code cho interface error.

Để tạo một error dù đơn giản thì chúng ta cũng phải định nghĩa một struct và tạo một thực thi code cho phương thức Error(). Để tránh điều này, Go cung cấp một package error được tích hợp sẵn và public, đó là hàm New. Hàm này yêu cầu một thông báo lỗi và trả về error. Ví dụ về hàm New:


package main import "fmt"
import "errors" func main() { // tạo error myErr := errors.New("Something unexpected happend!") // in ra thông báo lỗi fmt.Println(myErr)
}

Chúng ta thấy ham New yêu cầu string là thông báo lỗi và trả về một error. Vậy myError là kiểu gì ? Ta sẽ viết lại ví dụ bên trên và thử in kiểu trả về: image.png

Kết quả trả về ta có:

image.png

Như vậy kiểu dữ liệu của myErr là * errors.errorString, nó là một con trỏ cho errors.errorString.

Panic

Panic tương tự như việc đưa ra một Exception. Nói cách khác, một Panic là một Exception trong Go. Panice được gây ra bởi một lỗi trong lúc chạy và gọi thẳng đến hàm Panic trong Go.

Cách xử lý phổ biến khi gặp điều kiện bất thường trong Go là sử dụng errors là dủ cho hầu hết các trường hợp bất thường phát sinh.

Nhưng trong một số trường hợp chương trình không thể tiếp tục chạy bình thường khi lỗi. Torng trường hợp này chúng ta sử dụng Panic để shutdown chương trình. Khi một hàm gặp Panic, nó lập tức dùng xử lý, hàm bất kỳ được defer sẽ chạy và kiểm soát trả về cho phía gọi. Tiến trình này tiếp tục cho tới khi tất cả các hàm của goroutine hiện tại hoàn toàn được trả về, tại thời điểm đó chương trình in ra thông báo Panic, cùng với thông tin stack lỗi và kế thúc.

Khi một Panic được gọi xử lý thông thường của goroutine sẽ tạm dừng ngay lạp tức: Khi một chương trình bị panic, nó sẽ ngay lập tức giải phóng stack gọi Điều này sẽ tiếp tục cho tới khi chương trình lỗi và in ra thông tin stack lỗi hoặc tới khi hàm recover được gọi. Định nghĩa Panic

func panic(interface{})

Các tham số được truyền cho Panic sẽ được in ra khi chương trình chấm dứt. Để hiểu rõ hơn ta sẽ có ví dụ: image.png

Bên trên là chương trình đơn giản dùng để in ra tên đầy đủ của một người. Hàm fullName sẽ in ra tên đầy đủ cửa một người. Hàm này kiểm tra xem liệu con trỏ firstName và lastName có nil hay không. Nếu nil thì hàm sẽ gọi panic với thông báo đã được set sẵn. Thông báo lỗi này sẽ được in ra khi chương trình kết thúc.

Truyền vào WAN cho firstName, còn nil cho lastName. Do giá trị truyền vòa thỏa mãn điều kiện nil nên sẽ panic. Khi panic xảy ra, chương trình chấm dứt và in ra tham số được truyền cho panic kèm với thông tin stack lỗi.

Recover from panic

Recover là hàm được tích hợp sẵn trong Go và sử dụng để lấy lại kiểm soát của goroutine đang panic. Định nghĩa recover:

recover() interface{}

Hàm recover trả về giá trị được truyền cho hàm panic và không bị Side Effect. Nghĩa là nếu goroutine không bị panic, hàm recover sẽ trả về nil. Do đó việc kiểm tra giá trị trả về của recover có phải là nil hay không là cách tốt nhất để biết được rằng chương trình có bị panic không. Hãy cùng xem ví dụ sau:

package main import ( "fmt"
) func defFoo() { fmt.Println("defFoo() started") if r := recover(); r != nil { fmt.Println("This program is packing with value", r) } fmt.Println("defFoo() done")
} func normMain() { fmt.Println("normMain() started") defer defFoo() // defer defFoo call panic("HELP") // panic here } func main() { fmt.Println("main() started") normMain() // normal call fmt.Println("main() done")
}

Ta có kết quả:

Hàm normMain gọi bên trong hàm main() mà thực hiện defer khi gọi hàm defFoo(). Sau đó chương trình bị panic nên không có câu lệnh nào sau đấy được thực hiện, sau đó chương trình gọi hàm defer defFoo(), trong hàm này chúng ta có xử lý recover() để kiểm tra chương trình panic hay không. Do chương trình bị panic nên chúng ta in ra thông tin stack lỗi của Panic

image.png

Kết

Việc nhận biết lỗi và handle các lỗi đó một cách thông minh và tinh tế sẽ giúp cho việc debug cũng như tránh các biến cố xảy ra, do đó chúng ta không nên bỏ qua lỗi mà hãy nên xử lý chúng. Hy vọng bạn cảm thấy hữu ích với bài viết, have a nice day ❤️

Bài viết tham khảo:

Go – Xử lý lỗi: https://vngeeks.com/go-xu-ly-loi/ Go – Panic và recover: https://vngeeks.com/go-panic-va-recover/

Bình luận

Bài viết tương tự

- vừa được xem lúc

gRPC - Nó là gì và có nên sử dụng hay không?

Nhân một ngày rảnh rỗi, mình ngồi đọc lại RPC cũng như gRPC viết lại để nhớ lâu hơn. Vấn đề là gì và tại sao cần nó .

0 0 131

- vừa được xem lúc

Embedded Template in Go

Getting Start. Part of developing a web application usually revolves around working with HTML as user interface.

0 0 56

- vừa được xem lúc

Tạo Resful API đơn giản với Echo framework và MySQL

1. Giới thiệu.

0 0 60

- vừa được xem lúc

Sử dụng goquery trong golang để crawler thông tin các website Việt Nam bị deface trên mirror-h.org

. Trong bài viết này, mình sẽ cùng mọi người khám phá một package thu thập dữ liệu có tên là goquery của golang. Mục tiêu chính của chương trình crawler này sẽ là lấy thông tin các website Việt Nam bị deface (là tấn công, phá hoại website, làm thay đổi giao diện hiển thị của một trang web, khi người

0 0 237

- vừa được xem lúc

Tạo ứng dụng craw dữ liệu bing với Golang, Mysql driver

Chào mọi người . Lâu lâu ta lại gặp nhau 1 lần, để tiếp tục series chia sẻ kiến thức về tech, hôm nay mình sẽ tìm hiểu và chia sẻ về 1 ngôn ngữ đang khá hot trong cộng đồng IT đó là Golang.

0 0 75

- vừa được xem lúc

Golang: Rest api and routing using MUX

Routing with MUX. Let's create a simple CRUD api for a blog site. # All . GET articles/ .

0 0 54