接口的存在本质上是为了抽象化,这里理解的重点是:
一个类型如果拥有一个接口需要的所有方法,那么这个类型就实现了这个接口
这说明接口一个很重要的特点就是抽象,把不同类型的相同特点进行抽象统一。
下面举一个例子,比如我想实现一个通用的函数,能够支持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类型),这样就可以写出更方便和更通用的函数