1. main 函数定义
- Go:
,不能带参数,也不能有返回值。func main()
- C/C++:
,参数可以直接获取命令行参数。int main(int argc, char* argv[])
- C#:
,参数直接是命令行参数数组。static void Main(string[] args)
2. 包和导入(import/using/include)
- Go:用
声明包名,package
导入包。没有头文件,所有导出符号靠首字母大写。import
- C/C++:用
包含头文件,头文件和实现分离,符号导出靠#include
/public
。extern
- C#:用
和namespace
,一切都在类和命名空间里。using
3. 变量声明和初始化
- Go:类型在后,支持类型推断。
go
var x int = 10
y := 20 // 自动推断类型 - C/C++/C#:类型在前,C# 也支持
推断。var
c
int x = 10;
int y = 20;csharp
var y = 20;
4. 指针和内存管理
- Go:有指针,但没有指针运算,没有
这种写法。自动垃圾回收,无需手动 free。*p++
- C/C++:有指针和指针运算,需要手动管理内存(malloc/free, new/delete)。
- C#:有引用和指针(unsafe),自动垃圾回收。
5. 类、结构体和方法
- Go:没有类(class),有结构体(struct),可以给 struct 定义方法(func (t *Type) Method())。
- C++/C#:有类和结构体,支持继承和多态。
- C:只有 struct,没有方法。
6. 继承与接口
- Go:没有类继承,只有接口(interface),接口是隐式实现(只要实现了接口的方法就算实现了接口)。
- C++/C#:有显式继承和接口(C#),C++ 有虚继承和多重继承。
7. 错误处理
- Go:没有异常(exception),用多返回值
,需要手动判断错误。return value, err
- C++/C#:有 try-catch 异常机制。
- C:一般用返回值或 errno。
8. 并发模型
- Go:内置 goroutine 和 channel,非常容易写并发代码。
go
go func() { ... }()
- C++/C#:用线程库(std::thread, Task, Thread),语法更复杂。
9. 访问控制
- Go:没有 public/private 关键字。首字母大写即导出,小写即包内可见。
- C++/C#:有 public/protected/private。
10. 工程结构
- Go:推荐每个目录一个包,文件可以很多,但包名要统一。
- C++/C#:通常一个类一个文件,头文件和实现分离(C++),C# 全部在类和命名空间里。
11. 依赖管理
- Go:用 go.mod 管理依赖,自动下载。
- C++:用 make/cmake、vcpkg、conan 等。
- C#:用 NuGet。
12. 编译和部署
- Go:编译出一个静态二进制文件,部署非常简单。
- C++/C#:可能有动态库依赖,部署更复杂。
1. 多重继承
Go 语言没有类的多重继承,但可以通过多重组合和接口实现类似效果。
示例:多重组合
go
type Flyer interface {
Fly()
}
type Swimmer interface {
Swim()
}
type Duck struct{}
func (d Duck) Fly() { fmt.Println("Duck flying") }
func (d Duck) Swim() { fmt.Println("Duck swimming") }
func main() {
var f Flyer = Duck{}
var s Swimmer = Duck{}
f.Fly()
s.Swim()
}
你还可以通过 struct 组合多个“父类”:
go
type Animal struct{}
func (a Animal) Eat() { fmt.Println("eat") }
type Flyer struct{}
func (f Flyer) Fly() { fmt.Println("fly") }
type Swimmer struct{}
func (s Swimmer) Swim() { fmt.Println("swim") }
type SuperDuck struct {
Animal
Flyer
Swimmer
}
func main() {
d := SuperDuck{}
d.Eat()
d.Fly()
d.Swim()
}
这样
SuperDuck
就“拥有”了 Animal、Flyer、Swimmer 的所有方法,类似多重继承。
2. 虚方法(多态/重写)
Go 没有 virtual 关键字,但通过接口和方法重写实现多态。
示例:接口多态
go
type Animal interface {
Speak()
}
type Dog struct{}
func (d Dog) Speak() { fmt.Println("Woof") }
type Cat struct{}
func (c Cat) Speak() { fmt.Println("Meow") }
func makeItSpeak(a Animal) {
a.Speak()
}
func main() {
makeItSpeak(Dog{})
makeItSpeak(Cat{})
}
示例:组合和“重写”
如果组合 struct 后,子 struct 定义了同名方法,会“覆盖”父 struct 的方法(但不是严格的重写,只是隐藏)。
go
type Animal struct{}
func (a Animal) Speak() { fmt.Println("Animal sound") }
type Dog struct {
Animal
}
func (d Dog) Speak() { fmt.Println("Dog bark") }
func main() {
d := Dog{}
d.Speak() // Dog bark
d.Animal.Speak() // Animal sound
}
3. 总结
- 多重继承:用组合(嵌入多个 struct)和接口实现,方法名不冲突时全部可用。
- 虚方法/重写:用接口实现多态,用组合+同名方法实现“隐藏”。
- 接口:Go 的接口是实现多态的核心,鸭子类型,灵活且强大。
如果你有具体的 C#/C++ 复杂继承场景,想看 Go 里的实现方式,可以举例,我帮你写出 Go 代码对比!