Go vs Java vs C# 語法對比

1. 說明

  • 最近在學習Go,在學習的過程中為了加快學習速度、將新知識添加到已有知識體系架構中,總是會拿Go和其他開發語言進行對比,最終進行總結,於是就有了這篇文章。

  • 對於每一個知識點結束時會給出我個人的一些新的體會(即小結),另外我盡量給出引用相關資料,大家可以從源頭進行查看相關信息

2. 對比

  • 在進行開發語言知識點對比時盡量做到客觀

  • 對比的角度:基礎語法

  • PS:
      更高層次可以選擇從編程範式方面等進行對比。Go是函數式編程(或者叫指令式編程,支持面向對象特性),Java、C#是面向對象編程(基於類的面向對象編程)

2.1 關鍵字(keywords)

在開發的過程中,為了實現不同的業務或者解決問題,我們需要採用開發語言的各種關鍵字,經常使用的基本已經滿足需求,但是對於那些少量的最好有所了解,因為他們可能會提升你的開發效率或者提升性能。共勉!

2.1.1 Go

Go 有以下關鍵字(共25個)

break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var

參考資料

2.1.2 Java

Java 有以下關鍵字(共50個)

abstract continue for new switch
assert*** default goto* package synchronized
boolean do if private this
break double implements protected throw
byte else import public throws
case enum**** instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp** volatile
const* float native super while

說明

* not used
** added in 1.2
*** added in 1.4
**** added in 5.0

參考資料

2.1.3 C#

C# 有以下關鍵字(共77個),額外還有上下文關鍵字(共42個)

abstract event namespace static
as explicit new string
base extern null struct
bool false object switch
break finally operator this
byte fixed out throw
case float override TRUE
catch for params try
char foreach private typeof
checked goto protected uint
class if public ulong
const implicit readonly unchecked
continue in ref unsafe
decimal int return ushort
default interface sbyte using
delegate internal sealed virtual
do is short void
double lock sizeof volatile
else long stackalloc while
enum

參考資料

2.1.4 小結

從關鍵字數量上來說

Go最少(25)、Java次之(50)、C#最多(77)

從功能上來說

Go:官方對於底層封裝最少,看起來應對的業務場景相對較少,可能各種業務場景都需要自行進行封裝,當然這也和其設計初衷有關,但是和其他語言(例如:C)結合起來進行開發你會感到整個世界都是你的

Java:官方對於底層封裝相對(Go)較多,但是對於應付各種業務場景來說還是顯得不夠(需要自行進行類庫封裝),所以市場上各種輪子比較多(如果能夠深入原理,輕鬆走向架構師)

C#:官方對於底層封裝比較豐富、多樣化,不需要封裝即可應付大多數業務場景(輕鬆進行封裝,可以將面向對象概念發揮到極致),缺點也比較明顯比較容易造成開發人員懶惰、影響創新

總體說明

從關鍵字數量和功能可以看出該語言對於底層的封裝程度,但總體來說開發語言沒有對錯、優劣,在不同的場景選擇合適的開發語言即可

2.2 基本數據類型

思考一個問題:為什麼需要有數據類型?

  • 一些答案:
  • 《Java 編程的邏輯》 一書中對於其的解釋是 數據在計算機內部都是二進制表示的,不方便操作,為了方便操作數據,高級語言引入了數據類型和變量的概念
  • 我自己的理解(不一定正確):

  • 每一種數據類型所佔用的byte/bit是不同的(或者代表意義不同),他們的存在或者組合滿足了各種數據操作場景,進一步滿足了各種業務場景的需要(支持《Java 編程的邏輯》所說),便於CPU對內存進行操作,同時也便於進行數據存儲(和數據庫數據類型對應)。

2.2.1 Go 基本數據類型

共19個

int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
float32 float64 complex64 complex128 byte rune
bool string

說明

  • byte: alias for uint8 (不可兼容漢字)

  • rune: alias for int32, represents a Unicode code point (可兼容漢字)

  • string: 底層採用的是byte數組

參考資料:

2.2.2 Java 基本數據類型

共8個

byte short int long
float double boolean char

說明

  • string: 底層開始採用的是char數組(java 1.8 及之前版本),後面改為byte數組(java 1.9 及以後版本)

參考資料

2.2.3 C# 基本數據類型

共18個

byte sbyte
short ushort
int unit nint nuint
long ulong
float double decimal
bool char
object string dynamic

說明

  • 除nint、nuint和dynamic之外,都是.NET類型的別名

  • object、string、dynamic 為引用類型,其他都是值類型

  • string: 底層採用char數組

參考資料

2.2.4 小結

  • 無論哪一種開發語言,string類型變量值都是不可修改的,底層如採用byte數組實現將無法支持中文(中文需要3-4個位元組進行存儲),如需支持中文則需要採用其他類型數組(例如:char,rune)實現

2.3 值類型和引用類型

說值類型和應用類型就不得不講棧和堆

棧:是內存的一塊區域,用於存放值類型的的值

堆:也是內存的一塊區域,用於存放引用類型的值;但變量也會佔用棧上的內存(存放的不是具體數據類型的值,而是一個內存地址,其指向堆上的一塊內存區域,這片內存區域存儲的是對應變量的值)

2.3.1 Go 值類型和引用類型

  • 值類型:包含所有基本數據類型、數組、結構體

  • 引用類型:其他非值類型(包含:指針、slice切片、管道channel、接口interface、map、函數等)

2.3.2 Java 值類型和引用類型

  • 值類型:byte、short、int、long、float、double、boolean、char

  • 引用類型:其他非值類型

2.3.3 C# 值類型和引用類型

  • 值類型:sbyte、byte、short、ushort、int、uint、long、ulong、uint、nuint、float、double、decimal、bool、char、枚舉、結構體、Tuple

  • 引用類型:其他非值類型(class、interface、delegate、record、dynamic、object、string)

參考資料

2.3.4 小結

  • 無論哪一種開發語言,string類型變量值都是不可修改的,不同的語言可能將其歸類設置可能不一致(C#是引用類型,其他是值類型)

  • 數字類型、布爾類型、字符(即char,如果有)在三種語言中都為值類型(思考:為什麼?)

2.4 變量

  • 變量 = 變量名 + 數據類型 + 變量值

  • 變量:分為全局變量(可以簡單理解為:方法外部的變量)和局部變量(可以簡單理解為:方法內部的變量)

  • 無論是Go、Java、C# 對於變量、方法名稱都區分大小寫

2.5 運算

  • 電腦,也叫作計算機,誕生的最初目的是為了便於計算(算術運算)

  • 運算:分為算術運算、比較運算、邏輯運算

  • 現有計算機只會進行加法運算和邏輯運算,所有其他運算都將會被轉換為這兩種運算

2.5.1 Go 支持運算符

+ & += &= && == != ( )
-= =
* ^ *= ^= <- > >= { }
/ << /= <<= ++ = := , ;
% >> %= >>= ! . :
&^ &^=

說明

  • Go、Java、C# 均支持以上運算符

  • Go不支持左面++和–(只支持右面++和–,例如:number++)

2.5.2 Java 支持運算符

=
+ * / %
++ !
== != > >= < <=
&& || ?:
~ << >> >>> & ^ |

2.5.3 C# 支持運算符

  • C# 支持的運算符比較多,官方文檔將其分為:算術運算、比較運算、布爾邏輯運算、位運算、移位運算、相等運算

  • 具體運算符請查看相關 資料

2.5.4 小結

  • 不同軟件開發語言對於運算符的支持是不同的(也有一些是其定製化的)

  • 三種開發語言中,C# 對於底層的封裝更多(語法更加豐富)

參考資料

2.6 流程控制語句

  • 流程控制有2種:條件判斷和循環

  • 一般軟件開發語言都會實現這2種流程控制,否則只能執行簡單的自上而下(或者自下而上)流程

  • 不同流程控制的組合可以解決各種複雜疑難問題

  • 兩種流程控制

    1. 條件判斷
      if
      if/else
      if/else if/else
      switch
    1. 循環
      while
      do/while
      for
      foreach
  • 說明

  • Go 中switch語句更加強大,可以實現if/else if/else效果

  • Go 中沒有while、do/while,但可以使用for實現類似效果(for循環體中實現自增、條件判斷、break效果)

  • Go 中沒有foreach,但是可以通過for range實現類似效果,並且功能更加強大

2.7 函數(或方法)和類

  • 函數

  • Go 沒有方法重載,同一包內不允許出現相同方法名稱(排除首字母小寫的方法名稱,因為首字母小寫的方法只允許當前文件內部訪問)

  • Go 採用函數式編程,函數是一等公民,也是一種數據類型,可以直接賦值給變量。

  • Go 沒有try catch,但可以使用 defer/recover 來處理報錯信息

  • Go 和 C# 均支持同時返回多個參數(PS:Java不支持 也有可能我沒有發現

  • C# 方法參數可以有默認值(非類型默認值),Go、Java 則不允許

  • 內部拋出錯誤:Go、Java、C# 都允許拋出任意錯誤,Java 則可以在定義方法時指定哪些錯誤必須要處理

  • Go、Java、C# 均可以實現匿名函數

  • Go、Java、C# 均使用main函數作為程序入口方法

  • Go 無類的定義

  • Java、C# 都實現了基於類的面向對象,都將類作為一等公民,目前C#語法更為豐富和強大。抽象類、接口的靈活使用可以讓你的代碼非常靈活、業務發生變化時的改動更少

  • Java、C# 具有匿名類

  • C# 類構造函數參數支持默認值,Java不支持

  • Java、C# 的訪問修飾符區別比較大(特別是protected),C# 更豐富

  • Java 中代碼是通過包來組織的,C#是通過項目(例如:類庫)組織的

說明

  • Go、Java、C# 函數名稱、類名稱 都區分大小寫,對於命名規範要求也類似
  • 泛型

  • C# 對於泛型支持較為完善(性能最好,因為是複製一份代碼)

  • Java 是一種偽泛型(實際為Object類型)

  • Go 不支持泛型,但是可以通過 interface 來支持類似泛型的操作

總結

  • 學習方法:對比的最終目的是為了更加快速的建立知識體系、學習相關語言

  • 硬件限制:任何開發語言都逃不開硬件對於軟件的限制

  • 發展的眼光看待問題:Go、Java、C# 都在蓬勃發展,語法內容可能會有所變化,可以先建立一個知識樹,有變化時再去更新知識樹