編程語(yǔ)言比較:C 和 Go
Go 是一種現(xiàn)代編程語(yǔ)言,它很大程度上源自于 C 編程語(yǔ)言。因此,對(duì)于寫 C 程序的程序員來(lái)說(shuō),Go 應(yīng)該會(huì)感覺很熟悉。Go 讓編寫新程序變得容易,同時(shí)讓 C 程序員感覺熟悉,但避免了 C 編程語(yǔ)言的許多常見陷阱。
本文比較了一個(gè)簡(jiǎn)單的 C 和 Go 程序,該程序?qū)?shù)字從一相加到十。由于這個(gè)程序只使用了小的數(shù)值,所以結(jié)果不會(huì)變得太大,因此只使用了普通的整數(shù)變量。像這樣的循環(huán)在編程中非常常見,所以這個(gè)簡(jiǎn)單的程序很容易比較 C 和 Go。
如何在 C 中執(zhí)行循環(huán)
C 語(yǔ)言中最基本的循環(huán)是 for
循環(huán),它允許你對(duì)一組值進(jìn)行迭代。for
循環(huán)的基本語(yǔ)法是:
for (起始條件 ; 結(jié)束條件 ; 每次迭代后執(zhí)行的操作) { 循環(huán)內(nèi)要執(zhí)行的內(nèi)容 ; }
你可以編寫一個(gè) for
循環(huán),以打印從 1 到 10 的數(shù)字,將起始條件設(shè)置為 count = 1
,將結(jié)束條件設(shè)置為 count <= 10
。這樣就以 count
變量等于 1 時(shí)開始循環(huán)。結(jié)束條件意味著只要 count
變量小于或等于 10 ,循環(huán)就會(huì)繼續(xù)。
每次迭代之后,你使用 count = count + 1
將 count
變量的值增加 1。在循環(huán)內(nèi)部,你可以使用 printf
打印 count
變量的值:
for (count = 1; count <= 10; count = count + 1) {
printf("%d\n", count);
}
C 程序中常見的慣例是 ++
,它表示 “將某個(gè)值加一”。如果你寫 count++
,那就相當(dāng)于 count = count + 1
。大多數(shù) C 程序員會(huì)使用 count++
來(lái)編寫 for
循環(huán)中每次迭代后要執(zhí)行的操作,像這樣:
for (count = 1; count <= 10; count++) {
printf("%d\n", count);
}
這是一個(gè)示例程序,將從 1 到 10 的數(shù)字相加,然后打印結(jié)果。使用 for
循環(huán)對(duì)數(shù)字進(jìn)行迭代,但不要打印數(shù)字,而是將數(shù)字添加到 sum
變量中:
#include <stdio.h>
int main() {
int sum;
int count;
puts("adding 1 to 10 ..");
sum = 0;
for (count = 1; count <= 10; count++) {
sum = sum + count;
}
這個(gè)程序使用了兩個(gè)不同的 C 函數(shù)來(lái)向用戶打印結(jié)果。puts
函數(shù)打印引號(hào)中的字符串。如果你需要打印純文本,使用 puts
是個(gè)不錯(cuò)的選擇。
printf
函數(shù) 使用特殊字符在格式字符串中打印格式化的輸出。printf
函數(shù)可以打印許多不同種類的值。關(guān)鍵字 %d
打印十進(jìn)制(整數(shù))值。
如果你編譯并運(yùn)行這個(gè)程序,你會(huì)看到這個(gè)輸出:
adding 1 to 10 ..
The sum is 55
如何在 Go 中執(zhí)行循環(huán)
Go 提供了與 C 中非常相似的 for
循環(huán)。C 程序中的 for
循環(huán)可以直接轉(zhuǎn)換為 Go 的 for
循環(huán),并具有相似的表示形式:
for count = 1; count <= 10; count++ {
fmt.Printf("%d\n", count)
}
使用這個(gè)循環(huán),你可以直接轉(zhuǎn)換為 Go 的示例程序:
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("The sum is %d\n", sum)
}
雖然上述方式在 Go 中是正確的,但它并不是最常用的 Go 寫法。采用慣例是“使用與本地語(yǔ)言為人所知的表達(dá)方式”。任何語(yǔ)言的目標(biāo)都是高效的溝通,編程語(yǔ)言也不例外。在不同的編程語(yǔ)言之間進(jìn)行轉(zhuǎn)換時(shí),重要的是意識(shí)到盡管物似而意不同,一種編程語(yǔ)言中的典型寫法在另一種編程語(yǔ)言中可能不完全相同。
為使用更符合慣例的 Go,你可以進(jìn)行幾個(gè)小修改:
- 通過(guò)使用
+=
操作符來(lái)將sum = sum + count
更簡(jiǎn)潔地表達(dá)為sum += count
。 - 通過(guò)使用 分配并推斷類型運(yùn)算符 來(lái)表達(dá)
count := 1
而不是var count int
跟著count = 1
。:=
語(yǔ)法同時(shí)定義并初始化count
變量。 - 將
count
的聲明移到for
循環(huán)的頭中。這減少了一些認(rèn)知負(fù)擔(dān),也通過(guò)減少程序員在任何時(shí)候都必須心里記著的變量數(shù)目來(lái)提高可讀性。這個(gè)更改還通過(guò)在最接近其使用的地方和最小的范圍中聲明變量來(lái)增加安全性,從而減少了在代碼不斷演進(jìn)的過(guò)程中對(duì)變量進(jìn)行意外操作的可能性。
上述改動(dòng)的組合將產(chǎn)生以下代碼:
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("The sum is %d\n", sum)
}
你可以使用這個(gè) Go.dev 的 鏈接 在 Go 試驗(yàn)場(chǎng)中嘗試這個(gè)示例程序。
C 和 Go 相似但不同
通過(guò)在兩種編程語(yǔ)言中編寫相同的程序,你可以看到 C 和 Go 這兩種語(yǔ)言雖然相似但仍然不同。將從 C 轉(zhuǎn)換到 Go 時(shí)需要注意以下幾點(diǎn):
- 在 C 中,每個(gè)程序指令都必須以分號(hào)結(jié)尾。這告訴編譯器一個(gè)語(yǔ)句在哪里結(jié)束,下一個(gè)在哪里開始。在 Go 中,分號(hào)是有效的,但幾乎總是可以推斷出來(lái)。
- 雖然大多數(shù)現(xiàn)代 C 編譯器會(huì)為你將變量初始化為零值,但 C 語(yǔ)言規(guī)范指出,變量得到的是內(nèi)存中的任意值。Go 值總是初始化為其零值。這有助于使 Go 成為一種更具內(nèi)存安全的語(yǔ)言。這種差異在使用指針時(shí)變得更加有趣。
- 注意 Go 程序包對(duì)導(dǎo)入標(biāo)識(shí)符的使用方式。例如,
fmt
是一個(gè)實(shí)現(xiàn)格式化輸入和輸出的函數(shù),類似于 C 中的stdio.h
中的printf
和scanf
。fmt
程序包在 pkg.go.dev/fmt 中有文檔描述。 - 在 Go 中,
main
函數(shù)總是以退出代碼 0 返回。如果你希望返回其他值,你必須調(diào)用os.Exit(n)
,其中n
通常為 1 以表示錯(cuò)誤。這可以從任何地方調(diào)用,不僅僅是main
函數(shù),來(lái)終止程序。你可以在 C 中使用在stdlib.h
中定義的exit(n)
函數(shù)來(lái)實(shí)現(xiàn)相同的效果。