Go語(yǔ)言 程序源代碼基本元素介紹

2023-02-16 17:36 更新

相比很多其它流行語(yǔ)言,Go的語(yǔ)法相對(duì)簡(jiǎn)潔。 此篇文章將介紹編程中常用的代碼元素,并展示一份簡(jiǎn)單的Go程序代碼,以便讓剛開(kāi)始學(xué)Go編程的程序員對(duì)Go代碼結(jié)構(gòu)有一個(gè)大概的印象。

編程和程序代碼元素

簡(jiǎn)單來(lái)講,編程可以看作是以各種方式控制和組合計(jì)算機(jī)運(yùn)行中的各種操作,以達(dá)到各種各樣的目的。 一個(gè)操作可能從一個(gè)硬件設(shè)備讀取、或者向一個(gè)硬件設(shè)備寫(xiě)入一些數(shù)據(jù),從而完成一個(gè)特定的任務(wù)。 對(duì)于現(xiàn)代計(jì)算機(jī)來(lái)說(shuō),最基本的操作是底層計(jì)算機(jī)指令,比如CPU和GPU指令。 常見(jiàn)的硬件設(shè)備包括內(nèi)存、磁盤、網(wǎng)卡、顯卡,顯示器、鍵盤和鼠標(biāo)等。

直接操控底層計(jì)算機(jī)指令進(jìn)行編程是非常繁瑣和容易出錯(cuò)的。 高級(jí)編程語(yǔ)言通過(guò)對(duì)底層指令進(jìn)行一些封裝和對(duì)數(shù)據(jù)進(jìn)行一些抽象,從而使得編程變得直觀和易于理解。

在流行高級(jí)編程語(yǔ)言中,一個(gè)操作通常是通過(guò)函數(shù)(function)調(diào)用或者使用操作符(operator)運(yùn)算來(lái)完成的。 大多數(shù)高級(jí)編程語(yǔ)言都支持一些條件和循環(huán)控制語(yǔ)句。 這些條件和循環(huán)控制語(yǔ)句可以看作是特殊的操作。 它們的語(yǔ)法接近于人類語(yǔ)言,因此一個(gè)人寫(xiě)的代碼很容易被其他人理解。

在大多數(shù)高級(jí)編程語(yǔ)言中,數(shù)據(jù)通常被抽象為各種類型(type)和(value)。 一個(gè)類型可以看作是值的模板。一個(gè)值可以看作是某個(gè)類型的實(shí)例。 大多數(shù)編程語(yǔ)言支持自定義類型和若干預(yù)聲明類型(即內(nèi)置類型)。 一門語(yǔ)言的類型系統(tǒng)可以說(shuō)是這門語(yǔ)言的靈魂。

編程中常常會(huì)使用大量的值。 一些在編碼階段可確定的值可以用它們的字面形式(literal,即字面量)來(lái)表示。 為了編程靈活和不易出錯(cuò),其它的值一般使用變量(variable)和(具名)常量(named constant)來(lái)表示。

在《Go語(yǔ)言101》中,具名的函數(shù)、具名的值(包括變量和具名常量)、以及定義類型和類型別名將被統(tǒng)稱為代碼要素。 代碼要素名必須為標(biāo)識(shí)符(identifier)。

高級(jí)編程語(yǔ)言代碼將被編譯器或者解釋器轉(zhuǎn)換為底層機(jī)器碼進(jìn)行執(zhí)行。 為了幫助編譯器和解釋器解析高級(jí)語(yǔ)言代碼,一些單詞將被用做關(guān)鍵字(keyword)。 這些單詞不能被當(dāng)做標(biāo)識(shí)符使用。

很多現(xiàn)代高級(jí)語(yǔ)言使用(package)來(lái)組織代碼。 一個(gè)包必須引入(import)另一個(gè)包才能使用另一個(gè)包中的公有(導(dǎo)出的)代碼要素。 包名和包的引入名也都必須是標(biāo)識(shí)符。

盡管高級(jí)編程語(yǔ)言代碼比底層機(jī)器指令友好和易懂,我們還是需要一些注釋來(lái)幫助自己和其他程序員理解我們所寫(xiě)的代碼。 在下一節(jié)的程序示例中,我們可以看到很多注釋。

一個(gè)簡(jiǎn)單的Go示例程序

為了對(duì)各種代碼元素有一個(gè)更清楚的認(rèn)識(shí),讓我們來(lái)看一個(gè)簡(jiǎn)短的Go示例程序。 和很多其流行語(yǔ)言一樣,Go使用//來(lái)起始一個(gè)行注釋,使用一個(gè)/**/對(duì)來(lái)包裹一個(gè)塊注釋。

下面是這個(gè)Go示例程序。請(qǐng)注意閱讀其中的注釋。程序之后有更多解釋。

package main // 指定當(dāng)前源文件所在的包名

import "math/rand" // 引入一個(gè)標(biāo)準(zhǔn)庫(kù)包

const MaxRand = 16 // 聲明一個(gè)具名整型常量

// 一個(gè)函數(shù)聲明
/*
 StatRandomNumbers生成一些不大于MaxRand的非負(fù)
 隨機(jī)整數(shù),并統(tǒng)計(jì)和返回小于和大于MaxRand/2的隨機(jī)數(shù)
 個(gè)數(shù)。輸入?yún)?shù)numRands指定了要生成的隨機(jī)數(shù)的總數(shù)。
*/
func StatRandomNumbers(numRands int) (int, int) {
	// 聲明了兩個(gè)變量(類型都為int,初始值都為0)
	var a, b int
	// 一個(gè)for循環(huán)代碼塊
	for i := 0; i < numRands; i++ {
		// 一個(gè)if-else條件控制代碼塊
		if rand.Intn(MaxRand) < MaxRand/2 {
			a = a + 1
		} else {
			b++ // 等價(jià)于:b = b + 1
		}
	}
	return a, b // 此函數(shù)返回兩個(gè)結(jié)果
}

// main函數(shù),或主函數(shù),是一個(gè)程序的入口函數(shù)。
func main() {
	var num = 100
	// 調(diào)用上面聲明的StatRandomNumbers函數(shù),
	// 并將結(jié)果賦給使用短聲明語(yǔ)句聲明的兩個(gè)變量。
	x, y := StatRandomNumbers(num)
	// 調(diào)用兩個(gè)內(nèi)置函數(shù)(print和println)。
	print("Result: ", x, " + ", y, " = ", num, "? ")
	println(x+y == num)
}

將上面的程序代碼存盤到一個(gè)名為basic-code-element-demo.go 的文件中并使用下列命令運(yùn)行此程序:

$ go run basic-code-element-demo.go
Result: 46 + 54 = 100? true

在上面的示例程序中,單詞package、importconst、func、var、for、ifelsereturn均為關(guān)鍵字。 其它大多數(shù)單詞均為標(biāo)識(shí)符。 請(qǐng)閱讀關(guān)鍵字和標(biāo)識(shí)符以獲得更多關(guān)于關(guān)鍵字和標(biāo)識(shí)符的信息。

四個(gè)int(一個(gè)在第15行,另三個(gè)在第13行) 表示內(nèi)置基本類型int。int類型是Go中的基本整數(shù)類型之一。 第5行中的16、第17行中的0、 第20行中的1以及第30行的100均為整型字面量。 第35行的"Result: "是一個(gè)字符串字面量。 請(qǐng)閱讀基本類型和它們的字面量表示以獲取更多關(guān)于基本類型和它們的字面量的信息。 Go中的非基本類型(均為組合類型)將在以后的其它文章中介紹和解釋。

20行是一個(gè)賦值語(yǔ)句。 第5行聲明了一個(gè)具名常量,叫做MaxRand。 第15行和第30行使用標(biāo)準(zhǔn)變量聲明語(yǔ)句聲明了三個(gè)變量。 第17行的變量i以及第33行的變量xy是使用變量短聲明語(yǔ)句聲明的。 變量ab在聲明的時(shí)候被指定為int類型。 編譯器會(huì)自動(dòng)推導(dǎo)出變量i、num、xy的類型均為int類型,因?yàn)樗鼈兊某跏贾刀际钦妥置媪勘硎镜摹?請(qǐng)閱讀常量和變量以獲取什么是類型不確定值、類型推導(dǎo)、賦值、以及如何聲明變量和具名常量。

上面的示例程序中使用了很多操作符,比如第1719行的小于比較符<,第36行的等于比較符==,還有第2036行的加法運(yùn)算符+。 第35行中的+不是一個(gè)運(yùn)算符,它是一個(gè)字符串字面量中的一個(gè)字符。 一個(gè)使用操作符的操作中涉及到的值稱為操作值(有時(shí)也可稱為運(yùn)算數(shù))。 請(qǐng)閱讀常用操作符以獲取更多關(guān)于操作符的信息。 更多操作符將在后續(xù)其它文章中介紹。

3536行調(diào)用了兩個(gè)內(nèi)置函數(shù)printprintln。 從第13行到第26行聲明的函數(shù)StatRandomNumbers在第33行被調(diào)用。 第19行也調(diào)用了一個(gè)函數(shù) Intn。 這個(gè)函數(shù)聲明在math/rand標(biāo)準(zhǔn)庫(kù)包中。 請(qǐng)閱讀函數(shù)聲明及函數(shù)調(diào)用以獲取更多關(guān)于函數(shù)聲明及函數(shù)調(diào)用的信息。

(注意,一般printprintln這兩個(gè)內(nèi)置函數(shù)并不推薦使用。 在正式的項(xiàng)目中,我們應(yīng)該盡量使用fmt標(biāo)準(zhǔn)庫(kù)包中聲明的相應(yīng)函數(shù)。 《Go語(yǔ)言101》只在開(kāi)始的幾篇文章中使用了這兩個(gè)函數(shù)。)

1行指定了當(dāng)前源文件所處的包的名稱。 一個(gè)Go程序的主函數(shù)(main函數(shù))必須被聲明在一個(gè)名稱為main的包中。 第3行引入了math/rand標(biāo)準(zhǔn)庫(kù)包,并以rand做為引入名。 在這個(gè)包中聲明的Intn函數(shù)將在第19行被調(diào)用。 請(qǐng)閱讀代碼包和包引入,以獲取更多關(guān)于代碼包和包引入的信息。

表達(dá)式、語(yǔ)句和簡(jiǎn)單語(yǔ)句一文中介紹了什么是表達(dá)式和語(yǔ)句。特別地,此文列出了所有的簡(jiǎn)單語(yǔ)句類型。 在Go代碼中,各種流程控制代碼塊中的某些部分必須為簡(jiǎn)單語(yǔ)句,某些部分必須為表達(dá)式。

StatRandomNumbers函數(shù)的聲明體中使用了兩個(gè)流程控制代碼塊。 其中一個(gè)是for循環(huán)代碼塊,它內(nèi)嵌了另外一個(gè)代碼塊。 另外一個(gè)代碼塊是一個(gè)if-else條件控制代碼塊。 請(qǐng)閱讀基本流程控制語(yǔ)法以獲取更多關(guān)于流程控制代碼塊的信息。 更多的特殊的流程控制代碼塊將在以后的其它文章中介紹。

空行常常用來(lái)增加代碼的可讀性。 上面的程序中也包涵了很多注釋,但它們大多是為了Go初學(xué)者快速理解的目的而加入的。 我們應(yīng)該盡量使代碼自解釋,只在確實(shí)需要解釋的地方進(jìn)行注釋。

關(guān)于代碼斷行

像很多其它流行編程語(yǔ)言一樣,Go也使用一對(duì)大括號(hào){ and }來(lái)形成一個(gè)顯式代碼塊。但是在Go代碼中,編碼樣式風(fēng)格有一些限制。 比如,很多左大括號(hào){不能被放到下一行。 如果,上面的StatRandomNumbers被修改成如下所示,則上面的示例程序?qū)⒕幾g不通過(guò)。

func StatRandomNumbers(numRands int) (int, int)
{ // 編譯錯(cuò)誤:語(yǔ)法錯(cuò)誤
	var a, b int
	for i := 0; i < numRands; i++
	{ // 編譯錯(cuò)誤:語(yǔ)法錯(cuò)誤
		if rand.Intn(MaxRand) < MaxRand/2
		{ // 編譯錯(cuò)誤:語(yǔ)法錯(cuò)誤
			a = a + 1
		} else {
			b++
		}
	}
	return a, b
}

一些程序員不是很喜歡這些限制。但是這些限制有兩個(gè)好處:

  1. 它們使得Go程序編譯得非常快。
  2. 它們使得不同的Go程序員編寫(xiě)的代碼風(fēng)格類似,從而一個(gè)Go程序員寫(xiě)的代碼很容易被另一個(gè)程序員看懂。

我們可以閱讀代碼斷行規(guī)則一文以獲取更多關(guān)于代碼換行規(guī)則的細(xì)節(jié)。在目前,我們最好避免將左大括號(hào)放在下一行。 或者說(shuō),每行的非空起始字符不能是左大括號(hào)(但是,請(qǐng)記住,這不是一個(gè)普適的規(guī)則)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)