作为一个纯 C++ 选手,我将分享我在学习Go语言基础语法时发现的之间的联系。
在Go语言中,新引入了一个接口(interface)的概念
Go 语言中的接口(interface)定义了一组方法签名,而不包含具体的实现。接口类型并不关心实现这些方法的具体类型,只要一个类型实现了接口中定义的所有方法,它就满足该接口。
例如type Database interface { Save(data string) error }
type Database interface {
Save(data string) error
}
这里的Database是接口的名称,这个接口定义了一个方法 Save,它接受一个 string 类型的参数 data,并返回一个 error 类型的结果。
为什么要使用接口
使用接口的原因是为了定义行为,而不具体实现。在 Go 中,通过接口可以使代码更灵活、松耦合。例如,我们并不关心 Save 方法如何实现(它可以保存数据到文件、数据库、内存等),而只关心它是否能够被调用并成功执行。
任何类型只要实现了 Save(data string) error 这个方法,就自动成为 Database 接口的实现者,而不需要显式地声明实现了某个接口。这种方式也使得代码非常灵活,可以轻松替换不同的数据库实现。
如何去实现这个接口
假设我们有一个具体类型 SQLDatabase,它实现了 Database 接口中的 Save 方法。这样,SQLDatabase 就成为了 Database 接口的实现。
type SQLDatabase struct {
// SQLDatabase 的具体字段
}
func (db *SQLDatabase) Save(data string) error {
// 在这里实现保存数据的逻辑,例如保存到数据库
fmt.Println("Saving to SQL database:", data)
return nil // 假设没有错误
}
在这个例子中,SQLDatabase 类型通过实现 Save 方法,符合了 Database 接口的要求,因此 SQLDatabase 就自动实现了 Database 接口。
到此,大家可以发现,这个接口的实现就非常类似于C++类用的成员函数,类似于给SQLDatabase 类型添加了 Save 方法的成员函数。
如何去使用这个接口
可以像这样使用接口 Database 来接收任何实现了 Save 方法的对象,而不关心该对象的具体类型:
func SaveToDatabase(db Database, data string) error {
return db.Save(data)
}
在这里,SaveToDatabase 函数接受一个 Database 类型的参数 db,它可以是任何实现了 Save 方法的类型。你可以传递 SQLDatabase、MockDatabase 等不同的类型,而不需要修改 SaveToDatabase 的代码。
我们可以发现,在使用这个接口的时候,更类似于C++语言中多态的实现,而实现接口的过程更类似于成员函数中的虚函数。我们通过“父类” Database去调用子类SQLDatabase,从而实现了子类的虚函数Save。