Bài học theo mô-đun (2/5)
Xác nhận kiểu
Xác nhận kiểu trích xuất loại cụ thể từ một giá trị giao diện.
Bạn cần nó khi bạn có interface{} (hoặc giao diện "cao") trong
và cần coi nó là loại cụ thể để truy cập các trường hoặc
các phương thức không có trên giao diện.
Cú pháp
var i interface{} = "ciao"
s := i.(string) // "panic" form: panics if it's not a string
s, ok := i.(string) // "comma ok" form: ok = false if it's not a stringHai hình thức, hai ngữ nghĩa:
| Mẫu | Thành công | Thất bại |
|---|---|---|
v := i.(T) | v = giá trị loại T | hoảng loạn khi chạy |
v, ok := i.(T) | v=..., ok=true | v = giá trị 0 của T, ok=false |
Dạng “Comma ok”: an toàn nhất
var i interface{} = 42
if s, ok := i.(string); ok {
fmt.Println("è stringa:", s)
} else {
fmt.Println("non è stringa, ignoro")
}ok cho phép bạn xử lý trường hợp "nhầm loại" mà không cần lo lắng. Đó là
mẫu thành ngữ trong phần lớn các trường hợp.
Khẳng định với một giao diện
Khẳng định không chỉ hoạt động trên các loại cụ thể mà còn trên các loại khác giao diện:
type Closer interface { Close() error }
func tryClose(x interface{}) {
if c, ok := x.(Closer); ok {
c.Close()
}
}Một mẫu rất phổ biến trong thư viện chuẩn: "nếu đầu vào của tôi cũng
io.Closer, gọi Đóng ở cuối".
Khẳng định về con trỏ so với giá trị
Xác nhận phải khớp với loại động CHÍNH XÁC:
type Cat struct{}
func (c *Cat) Meow() {}
var a interface{} = &Cat{}
c1, ok := a.(*Cat) // ok = true
c2, ok := a.(Cat) // ok = false: it holds *Cat, not Cat*Cat và Cat là các loại riêng biệt cho hệ thống loại.
Khi nào nên sử dụng xác nhận và chuyển đổi loại
- Chỉ có 1 loại có thể, kiểm tra "phát hiện tính năng" (ví dụ: chuyển sang giao diện tùy chọn): xác nhận loại với
comma ok. - 2+ loại có thể, gửi qua nhiều nhánh: gõ switch (bài học tiếp theo).
Hãy thử nó
Sử dụng mẫu dấu phẩy ok để trích xuất một chuỗi từ i.
Hiển thị gợi ý
Cú pháp: `v, ok := i.(T)`.
Giải pháp khả dụng sau 3 lần thử
Nhập xác nhận vào int không có dấu phẩy ok (giả sử tôi chứa int).
Hiển thị gợi ý
Nếu không có `ok` bạn cho rằng loại đó là chắc chắn; nếu không thì hoảng sợ.
Giải pháp khả dụng sau 3 lần thử
Điều gì xảy ra với `s := i.(string)` nếu tôi chứa int?
var i interface{} = 42
s := i.(string)Tóm tắt lại
v := i.(T): hoảng sợ nếu động loại ≠ T.v, ok := i.(T): mẫu an toàn, kiểm traok.- Hoạt động cũng trên giao diện khác ("phát hiện tính năng").
Tvà*Tlà các loại riêng biệt cho xác nhận.- 1 loại → khẳng định; Hơn 2 loại → chuyển đổi loại.