接口的存在本质上是为了抽象化,这里理解的重点是:
一个类型如果拥有一个接口需要的所有方法,那么这个类型就实现了这个接口
这说明接口一个很重要的特点就是抽象,把不同类型的相同特点进行抽象统一。
下面举一个例子,比如我想实现一个通用的函数,能够支持json、CSV文件的读取
import (
"encoding/csv"
"fmt"
"os"
)
// FileReader 定义一个文件读取接口
type FileReader interface {
ReadFile(filename string) ([]byte, error)
}
// JSONReader 实现了 FileReader 接口,用于读取 JSON 文件
type JSONReader struct{}
func (jr JSONReader) ReadFile(filename string) ([]byte, error) {
return os.ReadFile(filename)
}
// CSVReader 实现了 FileReader 接口,用于读取 CSV 文件
type CSVReader struct{}
func (cr CSVReader) ReadFile(filename string) ([]byte, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
return csv.NewReader(f).ReadAll()
}
func processFile(reader FileReader, filename string) error {
data, err := reader.ReadFile(filename)
if err != nil {
return err
}
fmt.Printf("Processed file %s: %q\n", filename, data)
return nil
}
func main() {
jsonReader := JSONReader{}
err := processFile(jsonReader, "data.json")
if err != nil {
fmt.Println("Error processing JSON file:", err)
}
csvReader := CSVReader{}
err = processFile(csvReader, "data.csv")
if err != nil {
fmt.Println("Error processing CSV file:", err)
}
}
上面这个例子中,重点关注的是 processFile 这个函数,它实现了不管什么类型(json、CSV)的文件,都可以处理
因为json、CSV都有一个步骤,就是读取,这样可以把这个步骤抽象出来(都属于一种Reader类型),这样就可以写出更方便和更通用的函数