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種流程控制,否則只能執行簡單的自上而下(或者自下而上)流程
不同流程控制的組合可以解決各種複雜疑難問題
兩種流程控制
- 條件判斷
if
if/else
if/else if/else
switch
- 循環
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# 都在蓬勃發展,語法內容可能會有所變化,可以先建立一個知識樹,有變化時再去更新知識樹