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效果。(PS:經 “吉良吉影” 大佬的指出發現從C# 8.0開始,C#也支援類似功能了,請檢視資料switch expression和constant pattern)
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# 都在蓬勃發展,語法內容可能會有所變化,可以先建立一個知識樹,有變化時再去更新知識樹