Giao diện, giao diện {}, chuyển đổi
Một giao diện trong Go chỉ định mộtbộ phương pháp. Bất kỳ loại nào triển khai bộ phương pháp này được cho làtriển khai giao diện.
Một giao diện được triển khai không đồng nhất. Không códụng cụtừ khóa, được sử dụng trong các ngôn ngữ khác. Nếu một kiểu xác định toàn bộ tập phương thức của một giao diện, nó sẽ thực hiện nó. Nó được gọi là nhập cấu trúc, thời gian biên dịch tương đương vớigõ vịt.
Nếu nó đi như vịt, bơi như vịt và lang thang như vịt, đó là vịt
Quan trọng: trong Go, giao diện tóm tắt một tập hợp các phương thức (hành động), không phải dữ liệu.
Thí dụ
Ví dụ sau được lấy từCách sử dụng giao diện trong Gominh họa giao diện cơ bản của Động vật có thể Nói và các cấu trúc khác nhau đáp ứng giao diện:
type Animal interface {
Speak() string
}
type Dog struct {
}
func (d Dog) Speak() string {
return “Woof!”
}
type Cat struct {
}
func (c Cat) Speak() string {
return “Meow!”
}
type Llama struct {
}
func (l Llama) Speak() string {
return “???”
}
type JavaProgrammer struct {
}
func (j JavaProgrammer) Speak() string {
return “Design patterns!”
}
Bạn có thể chế tạo [] Động vật và chạySpeak()
về nội dung của nó:
func main() {
animals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}}
for _, animal := range animals {
fmt.Println(animal.Speak())
}
}
Giao diện trống
CácAnimal
giao diện nhỏ và đẹp, nhưng có một thứ thậm chí còn đơn giản hơn, nhưng có một khái niệm phức tạp để hiểu cho người mới bắt đầu: giao diện trống.
interface{}
là giao diện trống của Go, một khái niệm chính. Mọi loại thực hiện nó theo định nghĩa.
Giao diện là một kiểu, vì vậy bạn có thể xác định ví dụ:
type Dog struct {
Age interface{}
}
và bạn cũng có thể chuyển kiểu giao diện trống làm tham số hàm:
func Eat(t interface{}) {
// ...
}
Chấp nhậninterface{}
không có nghĩa là hàm chấp nhận bất kỳ kiểu nào, mà có nghĩa là Eat chấp nhận một giá trịinterface{}
kiểu.
Trong thời gian chạy, Go sẽ chuyển đổi giá trị thực tế được chuyển thànhinterface{}
giá trị.
Nếu bạn xác định một trường trong cấu trúc với kiểuinterface{}
, bạn có thể gán cho nó một giá trị thuộc bất kỳ loại nào. Ví dụ:
package main
import “fmt”
type Dog struct {
Age interface{}
}
func main() {
dog := Dog{}
dog.Age = “3”
fmt.Printf("%#v %T\n", dog.Age, dog.Age)
<span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span> = <span style="color:#ae81ff">3</span>
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Printf</span>(<span style="color:#e6db74">"%#v %T\n"</span>, <span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span>, <span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span>)
<span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span> = <span style="color:#e6db74">"not really an age"</span>
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Printf</span>(<span style="color:#e6db74">"%#v %T"</span>, <span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span>, <span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span>)
}
bản in
"3" string
3 int
"not really an age" string
Tất nhiên điều này không giới hạn ở các loại cơ bản: bạn có thể lưu trữ một lát cắt, một bản đồ, bất kỳ cấu trúc tùy chỉnh nào trong đó.
Cách giao diện được thể hiện bên trong
Nội bộ, một giao diệngiá trịlà haiwords
, tập hợp các byte.
Một từ trỏ đến loại giá trị cơ bản. Một từ trỏ đến dữ liệu.
Chuyển đổi
Khi chúng tôi đã làmanimals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}}
trước đây, Go đã tự động chuyển đổi tất cả các loại động vật cụ thể của chúng tôi thành loại Động vật. Mọi phần tử của lát cắt đó bây giờ là kiểu Động vật, với kiểu cơ bản trỏ đến các loài cụ thể, như Chó, Mèo và Llama.
Nhưng nếu một phương thức chấp nhận[]interface{}
ví dụ, chúng ta không thể chỉ vượt quaanimals
với nó, bởi vì loại không phù hợp. Chúng ta cần phảichuyển đổi rõ ràng từngAnimal
đến mộtinterface{}
trước đó, với một vòng lặp, như được mô tả trongTôi có thể chuyển đổi [] T sang [] giao diện {} khôngCâu hỏi thường gặp:
t := []int{1, 2, 3, 4}
s := make([]interface{}, len(t))
for i, v := range t {
s[i] = v
}
Xác định loại cơ bản của mộtinterface{}
Nếu một giá trị thuộc loạiinterface{}
, bạn có thể muốn xác định loại cơ bản. Làm sao? Khi bật công tắc.(type)
, giốngLượt đi hiệu quảgiải thích:
Một công tắc cũng có thể được sử dụng để khám phá kiểu động của một biến giao diện. Việc chuyển kiểu như vậy sử dụng cú pháp của xác nhận kiểu với kiểu từ khóa bên trong dấu ngoặc đơn. Nếu switch khai báo một biến trong biểu thức, biến đó sẽ có kiểu tương ứng trong mỗi mệnh đề. Việc sử dụng lại tên trong những trường hợp như vậy cũng rất dễ hiểu, trong trường hợp đó, khai báo một biến mới có cùng tên nhưng khác kiểu trong mỗi trường hợp.
var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
fmt.Printf("unexpected type %T\n", t) // %T prints whatever type t has
case bool:
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}
Các hướng dẫn về go khác:
- Sử dụng NGINX Reverse Proxy để phục vụ các dịch vụ Go
- Tạo bản sao của cấu trúc trong Go
- Khái niệm cơ bản về Máy chủ Web Go
- Sắp xếp loại bản đồ trong Go
- Tóm lại về con trỏ
- Giải thích về Thẻ Go
- Định dạng Ngày và Giờ
- Xử lý JSON với Go
- Đi các chức năng đa dạng
- Go Strings Cheat Sheet
- Giải thích về giao diện trống rỗng
- Gỡ lỗi Go với VS Code và Delve
- Named Go trả về các tham số
- Tạo chuỗi và số ngẫu nhiên trong Go
- Cấu trúc hệ thống tệp của một dự án Go
- Thuật toán tìm kiếm nhị phân được triển khai trong Go
- Sử dụng cờ dòng lệnh khi di chuyển
- GOPATH giải thích
- Xây dựng ứng dụng Dòng lệnh với Go: lolcat
- Xây dựng lệnh CLI với Go: coway
- Sử dụng Shell Pipes with Go
- Hướng dẫn về CLI: nhân bản may mắn
- Liệt kê các tệp trong một thư mục với Go
- Sử dụng Go để lấy danh sách các kho từ GitHub
- Tiếp tục, nối một đoạn chuỗi vào một tệp
- Chuyển đổi một chuỗi thành một lát byte
- Hình dung các đóng góp Git địa phương của bạn với Go
- Bắt đầu với Go cấu hình CPU và bộ nhớ
- Giải quyết lỗi "không hỗ trợ lập chỉ mục" trong chương trình Go
- Đo thời gian thực thi trong chương trình cờ vây
- Xây dựng Trình thu thập thông tin web với Go để phát hiện các tiêu đề trùng lặp
- Thực hiện các phương pháp hay nhất: Con trỏ hoặc bộ thu giá trị?
- Thực hiện các phương pháp hay nhất: Bạn nên sử dụng một phương pháp hay một hàm?
- Đi cấu trúc dữ liệu: Đặt
- Go Maps Cheat Sheet
- Tạo triển khai cho các loại chung trong Go
- Truy cập cấu trúc dữ liệu: Từ điển
- Truy cập cấu trúc dữ liệu: Bảng băm
- Triển khai sự kiện Người nghe trong Đi qua các Kênh
- Truy cập cấu trúc dữ liệu: Ngăn xếp
- Truy cập cấu trúc dữ liệu: Hàng đợi
- Đi cấu trúc dữ liệu: Cây tìm kiếm nhị phân
- Đi cấu trúc dữ liệu: Đồ thị
- Truy cập cấu trúc dữ liệu: Danh sách được liên kết
- Hướng dẫn đầy đủ về cấu trúc dữ liệu Go
- So sánh các giá trị Go
- Go có hướng đối tượng không?
- Làm việc với Cơ sở dữ liệu SQL trong Go
- Sử dụng các biến môi trường trong Go
- Xem hướng dẫn: REST API được hỗ trợ bởi PostgreSQL
- Bật CORS trên Máy chủ Web Go
- Triển khai ứng dụng Go trong Docker Container
- Tại sao Go là một ngôn ngữ mạnh mẽ để học với tư cách là một nhà phát triển PHP
- Đi, xóa ký tự dòng mới io.Reader.ReadString
- Bắt đầu, cách xem các thay đổi và xây dựng lại chương trình của bạn
- Đi, đếm tháng kể từ một ngày
- Truy cập thông số HTTP POST trong Go