聞道Go語言,6月齡必知必會

大家好,我是馬甲哥,

學習新知識, 我的策略是模仿-->歸納--->舉一反三,

在同程倒騰Go語言一年有餘,本次記錄《聞道Go語言,6月齡必知必會》,形式是同我的主力語言C#做姿勢對比。

1. 宏觀預覽

1.1 常見結構對比

某些不一定完全對標,實現方式,側重點略點差異。

go語言 --- C#語言 ---
module assembly
pkg go get github.com/thoas/go-funk package Install-Package Masuit.Tools.Core
struct class
pointer reference
net/http web腳手架、 httpclient ASP.NETCore、httpclient
net/http/DefaultServeMux ASP.NETCore腳手架路由
goroutine 異步任務、 async/await
channel CSP TPL data flow CSP模型在C#並非主流
context timeout、 cancellation-token

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 *ArbitraryType
type 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關鍵字的行爲效果是一樣的。

推薦附加閱讀

本文限於篇幅,只記錄了go語言和C#語言的入門6月齡的核心差異點和重難點,高手繞道, 後續會不斷完善, 請有心人持續關注左下角原文, 如果能點贊更是莫大的鼓勵。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章