可能由于go语言由c语言之父参与开发的缘故,Go语言实现类的方法与Linux内核中C语言实现类的方法有一些相似之处。你没看错,是c语言实现类的方法,而不是原生支持面向对象的C++。go和c的异同主要如下:
1. 实现类
在Go和C中,结构体都是用于封装数据的基本单元。
-
Go:
type MyStruct struct {MyVar int }
-
C:
struct MyStruct {int MyVar; };
2.实现类成员方法
-
C:c语言用函数指针实现类方法
在C语言中,方法(或行为)通常通过函数指针来实现。结构体中包含函数指针,以实现类似于面向对象编程中的方法。struct MyStruct {int MyVar;void (*MyFunction)(struct MyStruct*); };void myFunctionImplementation(struct MyStruct* self) {// function implementation }struct MyStruct instance = { .MyVar = 10, .MyFunction = myFunctionImplementation };
-
Go:Go语言通过接收者参数实现类方法
type MyStruct struct {MyVar int }func (m MyStruct) MyValueMethod() {// method implementation }func (m *MyStruct) MyPointerMethod() {// method implementation }
3. 组合模拟继承
Go语言强调组合而非继承,通过将一个结构体嵌入到另一个结构体中实现代码复用。这与C语言中通过包含其他结构体实现组合的方式类似。
-
Go:
type Base struct {BaseVar int }func (b Base) BaseMethod() {// base method implementation }type Derived struct {BaseDerivedVar int }
-
C:
struct Base {int BaseVar;void (*BaseMethod)(struct Base*); };struct Derived {struct Base base;int DerivedVar; };
4. 实现多态的方法
在C语言中,多态性通常通过函数指针实现,而在Go中则通过接口实现。
-
C:子类是父类结构体的不同实现,给不同子类结构体实例传入不同函数指针实现多态,但因为子类都是同一种结构体,所以可以通过同一种参数传入同一个函数而不会被类型检查所区分。
struct Animal {void (*Speak)(struct Animal*); };void DogSpeak(struct Animal* self) {printf("Woof!\n"); }void CatSpeak(struct Animal* self) {printf("Meow!\n"); }struct Animal dog = { .Speak = DogSpeak }; struct Animal cat = { .Speak = CatSpeak };void makeAnimalSpeak(struct Animal* animal) {animal->Speak(animal); }
-
Go:将不同结构体作为不同函数的接收者,没有父类和子类的关系,只要实现了相同的接口就可以实现多态,甚至都不是同一类结构体,因为animal和cat dog的定义毫无关联。而且makeAnimalSpeak函数不需要显式地检查传入参数的类型,编译器会确保只有实现了Animal接口的类型才能赋值给Animal接口类型的变量。有点像python的鸭子类型。
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!" }func makeAnimalSpeak(a Animal) {fmt.Println(a.Speak()) }
总结
虽然Go语言和C语言在语法和特性上有很大不同,但在实现类和方法的基本理念上有一些相似之处。两者都使用结构体来封装数据,并通过函数或方法来实现行为。在C语言中,多态性通过函数指针实现,而在Go语言中则通过接口实现。