阅读量:2
可能由于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 { Base DerivedVar 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语言中则通过接口实现。