写点什么

闻道 Go 语言,6 月龄必知必会

  • 2022-10-25
    四川
  • 本文字数:1865 字

    阅读完需:约 6 分钟

大家好,我是马甲哥,


学习新知识, 我的策略是模仿-->归纳--->举一反三,


在同程倒腾 Go 语言一年有余,本次记录《闻道 Go 语言,6 月龄必知必会》,形式是同我的主力语言 C#做姿势对比。


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#语言基本是一样的



- go语言else if、 else 不允许换行,C#对此无要求。- C#要求[使用括号包围]条件判断语句。
复制代码
switch -- case [break]


- go语言case语句默认都加上了break,加不加都一样,满足当前case,执行完就会跳出当前switch, 不会一直case下去;- C#语言执行分支需要主动break, 若没有break,表示共用可用的执行体。
复制代码

2.3 循环


  • go 语言只有 for 循环,C#还有 while, do while


使用 for 来体现 while/do while



3. 面向对象

封装 抽象 继承 多态


同样是面向对象编程语言,go 用结构体来体现,C#常用类来体现。


封装

通常 go 语言基于结构体、接收者函数来[封装/提炼]事物和行为。


  • 接收者函数分为: 值接收者函数、指针接收者函数。

  • 两种都能体现封装, 但[指针接收者函数]内的操作会体现到入参。

  • 不管是值,还是指针,都能调用指针接收者函数/值对象接受者函数,效果还是如上一点一致。


C# 显式使用Class struct等结构来封装数据和行为。

抽象 + 继承

go 语言没有抽象函数、抽象类的说法,有接口抽象 和父子类继承关系。


接口将具有共性的方法放在一起,其他任何类型只要实现了这些方法就是实现了接口,俗称鸭子模式。


C#具备语义化的继承/抽象/多态, 显式继承。


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 *ArbitraryTypetype ArbitraryType int


C# unsafe关键字可用在函数、属性、构造函数、代码块。


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 月龄的核心差异点和重难点,高手绕道, 后续会不断完善, 请有心人持续关注左下角原文, 如果能点赞更是莫大的鼓励。

发布于: 刚刚阅读数: 4
用户头像

急性子,入戏慢。 2018-06-17 加入

阿里云社区专家博主,同程旅行基础架构 ; 热衷分享,执着于阅读写作,佛系不水文,有态度公众号:《精益码农》; 持续输出高价值Go、.NET、云原生原创文章。

评论

发布
暂无评论
闻道Go语言,6月龄必知必会_有态度的马甲_InfoQ写作社区