簡單對比一下 C 與 Go 兩種語言

来源:https://www.cnblogs.com/englyf/archive/2023/08/25/17655883.html
-Advertisement-
Play Games

以下內容為本人的學習筆記,如需要轉載,請聲明原文鏈接[ 微信公眾號「ENG八戒」](https://mp.weixin.qq.com/s/U6jIT837x5Yxe6Ev1aMDsA)[https://mp.weixin.qq.com/s/U6jIT837x5Yxe6Ev1aMDsA](https: ...


以下內容為本人的學習筆記,如需要轉載,請聲明原文鏈接 微信公眾號「ENG八戒」https://mp.weixin.qq.com/s/U6jIT837x5Yxe6Ev1aMDsA

使用一個簡單的計數程式將古老的 C 語言與現代 Go 進行比較。

Go 是一種現代編程語言,追溯其歷史大部分源自編程語言 C。所以,任何熟悉 C 語言的開發者都可能會覺得 Go 很熟悉。C 程式員使用 Go 編寫新程式變得容易,同時避免了 C 編程語言的許多常見缺陷。

下麵通過實現一個簡單的加法邏輯,來比較 C 和 GO 的區別。該程式將數字從一加到十,計算過程和結果數值都比較小,所以代碼僅使用普通整數變數。像這樣的迴圈邏輯在編程中很常見,所以對比效果會顯而易見。

C 語言做迴圈

C 語言中的基本迴圈是 for 迴圈,它可以實現對一組值的迭代訪問。

for 基本語法:

for (初始化條件; 判斷條件為真; 每次迴圈之後的操作) {
  // do something;
}

比如,可以編寫一個迴圈,初始化條件時設置變數 count 為 1,然後判斷 count <= 10 為真時執行 {} 內的語句,在再次執行條件判斷之前,對變數 count 增加 1。直到判斷 count <= 10 為假就退出迴圈。

在每次迭代後,對變數 count 增加 1,除了常規的 count = count + 1 書寫格式之外,也可以對變數採用 ++ 的自加操作符,這種變通可以使得代碼更簡潔易讀。

在迴圈內部,為了直觀查看變數的變化過程,可以使用標準庫函數 printf 列印變數 count 的值:

for (int count = 1; count <= 10; count ++) {
  printf("%d\n", count);
}

為了演示完整的邏輯,下麵是一個示常式序,將數字從 1 加到 10,然後列印和的結果。

#include <stdio.h>
int main()
{
  puts("adding 1 to 10 ..");
  int sum = 0;
  for (int count = 1; count <= 10; count ++) {
    sum += count;
  }
  
  printf("sum is %d\n", sum);
  return 0;
}

上面的代碼使用了兩種函數把信息列印出來,最終輸出到標準輸出 stdout。puts 函數列印一個字元串,直到遇到字元串的空字元,而 printf 函數支持格式化列印,非常靈活,所以更常用。關鍵字 %d 表示列印一個十進位(或整數)值,\n 表示換行符。

如果編譯並運行該程式,你將看到以下輸出:

adding 1 to 10 ..
sum is 55

GO 語言做迴圈

在 GO 語言中,同樣提供了 for 迴圈,而且與 C 語言中的 for 迴圈語法非常相似,甚至可以直接轉換成 GO 的書寫格式。

下麵為了直觀查看變數的變化過程,在迴圈內部同樣使用方法列印變數 count 的值:

var count int
for count = 1; count <= 10; count ++ {
  fmt.Printf("%d\n", count)
}

fmt 是包名,使用包之前需要先導入,用關鍵詞 import。C 語言中就沒有導入包的概念,只能通過包含頭文件 .h 來引入其它現成模塊。

fmt 實現了類似 C 語言的列印輸出 printf 和讀取輸入 scanf。fmt.Printf 方法也是支持格式化輸出的,甚至格式變數就是從 C 語言的 printf 派生而來。

在 C/C ++ 代碼中,比較推薦的編碼規範中通常每行是只寫一句操作語句,雖然語法上多個操作語句是允許書寫在同一行的,但這樣易讀性就很差。有沒有發現,在每行 GO 語句的末尾都沒有分號 ';' 了? 因為 GO 編譯器預設每行就是一個語句,這樣其實是強制提高了代碼的可讀性。

再來看看 GO 語言實現的完整邏輯,基於上面的 C 語言代碼版本直接翻譯如下

package main
import "fmt"

func main() {
  var sum, count int
  fmt.Println("adding 1 to 10 ..")

  for count = 1; count <= 10; count ++ {
    sum = sum + count
  }
  fmt.Printf("sum is %d\n", sum)
}

上面的代碼是有效和可以正確運行輸出的,但是這很不 GO ! GO 不單單是一門語言,也是一種態度。

有沒有看到 C 語言版本中, for 迴圈里的初始化條件是可以同時聲明定義並賦值變數的?換成在 GO 中是否也支持類似操作?

在 GO 中,有個聲明變數並賦值的操作符 :=,就可以做到

for count := 1; count <= 10; count ++ {
  sum = sum + count
}

另外,你如果再細心一點可能會發現,GO 代碼里聲明定義的變數會被預設初始化為 0,而 C 代碼中定義的變數如果未經初始化會是任何未知的值,如此看來 GO 的安全性有了很大的提高。

變數的生命周期管理對開發者來說是很耗費心智的,所以很多時候變數的聲明定義都是應該儘量靠近使用的地方,並且縮窄變數的生命周期,對於事故的發生可以有效縮小排查錯誤的範圍,簡直就是在打救程式員的生命啊。

再來看看,優化後的 GO 範式代碼

package main
import "fmt"

func main() {
  fmt.Println("adding 1 to 10 ..")
  var sum int
  for count := 1; count <= 10; count++ {
    sum += count
  }

  fmt.Printf("sum is %d\n", sum)
}

看到這裡,和 C 代碼的 main 函數比起來,GO 的 main 函數沒有顯式的返回值。實際上,GO 的 main 函數預設返回值 0,如果需要返回其它值,可以調用 os.Exit(n) 返回值 n,這個方法可在任何位置調用,程式會在調用該方法後會終止運行並退出,就類似 C 語言中的標準庫函數 exit(n) 一樣。

簡單回顧

從上面的邏輯實現過程來看,兩種語言實現過程差別不大,語法上是有差別的,書寫的習慣其實就透露著各自的態度。

雖然老氣橫秋的 C 語言代碼很多,但是如果按照現代 C 語言書寫規範來看,GO 的代碼是何其相似。

雖然你會說新出來的語言有很多方便到爆炸的語法糖。但問題是,語言的精髓是語法糖嗎?答案不唯一,酸甜苦辣唯有嘗過的人才知道。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • HP DP(Data Protector Manager)上一個剛剛遷移升級的資料庫備份作業失敗,具體失敗信息如下 .................................RMAN-08503: piece handle=c-1684727642-20230822-00 comment=A ...
  • # [TOC] [Android開發中的NDK到底是什麼?(詳細解析+案例) - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/415536928) # NDK介紹 **(1)簡介** **定義:**`Native Development Kit`,是 ` ...
  • 我司存在記憶體為1G RAM的設備,屬於低記憶體設備,經常會出現記憶體很緊張的場景,也容易因此導致一系列七七八八的邊際問題,故有必要瞭解Android系統的記憶體相關知識: 1. 瞭解記憶體的分配、回收方式 2. 瞭解OOM、LMK的相關機制 3. 瞭解Android系統記憶體相關調試方式 4. 瞭解Andro... ...
  • 在 vue 中,預設情況下,一個組件實例在被替換掉後會被銷毀。這會導致它丟失其中所有已變化的狀態——當這個組件再一次被顯示時,會創建一個只帶有初始狀態的新實例。但是 vue 提供了 keep-alive 組件,它可以將一個動態組件包裝起來從而實現組件切換時候保留其狀態。本篇文章要介紹的並不是它的基本 ...
  • 小程式超出大小,分包載入步驟 1.查看項目結構 2.分析主包大小 3.查閱參考文檔 4.結構調整 5.修改pages.json ...
  • ## 1.概述 1. React Router 以三個不同的包發佈到 npm 上,它們分別為: 1. react-router: 路由的核心庫,提供了很多的:組件、鉤子。 2. **react-router-dom:** 包含react-router所有內容,並添加一些專門用於 DOM 的組件,例如 ...
  • ##一、定義 **提供一個創建一系列相關或互相依賴對象的介面,而無須指定他們具體的類,抽象工廠模式是一種創建型模式。** ##二、描述 **抽象工廠比工廠方法的抽象程度更高,通過引入了工廠等級結構,解決了簡單工廠模式中工廠類職責太重的原則。為了更好的理解抽象工廠模式,引入兩個概念:** **1、產品 ...
  • 我們團隊一直在持續推進業務系統的體系化治理工作,在這個過程中我們沉澱了自己的DDD腳手架項目。本文主要是梳理和總結了DDD腳手架使用中的編碼規範以及遇到的問題。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...