闻道 Go 语言,6 月龄必知必会
大家好,我是马甲哥,
学习新知识, 我的策略是模仿-->归纳--->举一反三,
在同程倒腾 Go 语言一年有余,本次记录《闻道 Go 语言,6 月龄必知必会》,形式是同我的主力语言 C#做姿势对比。
![](https://static001.geekbang.org/infoq/4a/4abdfe45211166da01652d957737f969.png)
1. 宏观预览
1.1 常见结构对比
某些不一定完全对标,实现方式,侧重点略点差异。
1.2 访问级别
go 语言使用[首字母大小]写来体现公开/私有, 应用到 package struct function;
C#显式使用关键字来体现。
1.3 类型初始化
go 语言有两初始化的内置关键字
new : 用于分配内存(带内存零值),返回指针 new(int), new(Cat)
make : 只用于 slice、map、 channel 引用类型的初始化
C#基础类型使用字面量, 引用类型使用 new 关键字
2. 编码逻辑结构
2.1 顺序
这没什么好说的,都是至上而下, 遇到函数进函数堆栈。
go 语言每行代码后不需要加分号;C#语言每行代码后需要加分号。
go 对于括号的使用有要求: 斜对称, C#无要求。
2.2 分支
if --- elseif --- else
go 和 C#语言基本是一样的
![](https://static001.geekbang.org/infoq/4d/4d7fc6e2473674cec2b21bc8c8822565.png)
switch -- case [break]
![](https://static001.geekbang.org/infoq/c8/c82e1d1116249cc1e348c23839196d1d.png)
2.3 循环
![](https://static001.geekbang.org/infoq/74/74ace215f5272ca86013dfbc1b3b5517.png)
go 语言只有 for 循环,C#还有 while, do while
使用 for 来体现 while/do while
![](https://static001.geekbang.org/infoq/3b/3b2e30599fdf8a0673085b76ff221409.png)
![](https://static001.geekbang.org/infoq/38/38f022ccd46ef5f1e1a6170992c2b06e.png)
3. 面向对象
封装 抽象 继承 多态
同样是面向对象编程语言,go 用结构体来体现,C#常用类来体现。
![](https://static001.geekbang.org/infoq/4a/4a38c2dcec96cdddf36216ca466cda53.png)
封装
通常 go 语言基于结构体、接收者函数来[封装/提炼]事物和行为。
接收者函数分为: 值接收者函数、指针接收者函数。
两种都能体现封装, 但[指针接收者函数]内的操作会体现到入参。
不管是值,还是指针,都能调用指针接收者函数/值对象接受者函数,效果还是如上一点一致。
C# 显式使用Class
struct
等结构来封装数据和行为。
抽象 + 继承
go 语言没有抽象函数、抽象类的说法,有接口抽象 和父子类继承关系。
接口将具有共性的方法放在一起,其他任何类型只要实现了这些方法就是实现了接口,俗称鸭子模式。
C#具备语义化的继承/抽象/多态, 显式继承。
![](https://static001.geekbang.org/infoq/a7/a7c8359f4144e46e374e2aa817e5d40d.png)
4. 指针 vs 引用
指针指向一个内存地址; 引用指向内存中某个对象。
一般认为 go 是 C 语言的家族,但是 go 的指针弱化了 C 语言的指针操作,go 指针的作用仅操作其指向的对象, 不能基于地址这个概念做指针移位, 也不能基于地址这个概念做类型转化。
A value of a pointer type whose base type is T can only store the addresses of values of type T.
go 的指针简化了指针的使用,减少了指针出错的概率。
引用可看做是指针的抽象,也基于 code safe 的理由,不能在引用上做算术运算和低级别的取巧。
从这个意义上看,C#的引用等价于 go 的指针, 都是类型安全的指针。
另一方面, 两种语言都提供了对内存进行任意读写的姿势(非代码安全)。
go 的 unsafe.Pointer 本质是一个 int 指针。
type Pointer *ArbitraryType
、type ArbitraryType int
C# unsafe
关键字可用在函数、属性、构造函数、代码块。
![](https://static001.geekbang.org/infoq/fd/fdaf1db317765e806fe770ba41bbbd41.png)
5. goroutine vs async-await
表象
goroutine 由 go 的原生函数生成,只要前面加上 go 的语法关键字
go
(可以有形参,返回值会被忽略)。await/async 语法糖,简化了异步编程的姿势;实际会被编译器编译成一个状态机。
goroutine 是在 runtime 级别深度内置, async-await 是在 CLR 之上基于 C#语言构建。
核心对比
首先要知道: 线程是 cpu 调度的基本单位,不管是 goroutine 还是 async-wait 机制都是在尝试提高[cpu 调度线程的效率]。
go 在 os 内核线程之上,原生支持了轻量级的用户态线程 goroutine,堆栈很小,开销很小,(存在一个用户态逻辑处理器给线程投喂 goroutine)。
C#编译器生成的状态机,转化并管控基于线程池线程的主调任务、异步任务、后继任务。
两者支持并发的思路有明显差异:
go: 内核态线程切换开销大,故原生提供用户态线程,开销极小,天然支持高并发,且不轻易坠落到内核态, 是一个革命派的思路。
C#:async-await 针对线程做辗转腾挪,高效利用, 是一个改良派的思路。
异步
都具备异步的能力,go 语言没有 await 的概念,goroutine 在等待通道读操作时[挂起自身,并将 OS 线程释放给另一个 goroutine], 跟 C#执行时遇到 await 关键字的行为效果是一样的。
推荐附加阅读
https://grantjam.es/concurrency-comparing-golangs-channels-to-c-sharps-asyncawait/
https://techstacks.io/posts/6628/go-vs-csharp-part-1-goroutines-vs-async-await
本文限于篇幅,只记录了 go 语言和 C#语言的入门 6 月龄的核心差异点和重难点,高手绕道, 后续会不断完善, 请有心人持续关注左下角原文, 如果能点赞更是莫大的鼓励。
版权声明: 本文为 InfoQ 作者【有态度的马甲】的原创文章。
原文链接:【http://xie.infoq.cn/article/3396a3861aadbb345e9a6ba30】。文章转载请联系作者。
评论