Chuyển đến nội dung chính
Mô-đun 6 · Bài học 2 trong tổng số 527/50 trong khóa học~10 min
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

Go
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 string

Hai hình thức, hai ngữ nghĩa:

MẫuThành côngThất bại
v := i.(T)v = giá trị loại Thoảng loạn khi chạy
v, ok := i.(T)v=..., ok=truev = giá trị 0 của T, ok=false

Dạng “Comma ok”: an toàn nhất

Go
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:

Go
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:

Go
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ó

tập thể dục#go.m6.l2.e1
Nỗ lực: 0Đang tải…

Sử dụng mẫu dấu phẩy ok để trích xuất một chuỗi từ i.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Cú pháp: `v, ok := i.(T)`.

Giải pháp khả dụng sau 3 lần thử

tập thể dục#go.m6.l2.e2
Nỗ lực: 0Đang tải…

Nhập xác nhận vào int không có dấu phẩy ok (giả sử tôi chứa int).

Đang tải trình chỉnh sửa…
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ử

Quiz#go.m6.l2.e3
Sẵn sàng

Điều gì xảy ra với `s := i.(string)` nếu tôi chứa int?

Go
var i interface{} = 42
s := i.(string)
Tùy chọn trả lời

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 tra ok.
  • Hoạt động cũng trên giao diện khác ("phát hiện tính năng").
  • T và *T là 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.