Go 语言入门指南:基础语法和常用特性解析

67 阅读2分钟

作为一个纯 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 方法的类型。你可以传递 SQLDatabaseMockDatabase 等不同的类型,而不需要修改 SaveToDatabase 的代码。

我们可以发现,在使用这个接口的时候,更类似于C++语言中多态的实现,而实现接口的过程更类似于成员函数中的虚函数。我们通过“父类” Database去调用子类SQLDatabase,从而实现了子类的虚函数Save