
go的main方法理解為入口函數(shù),程序只執(zhí)行這一個函數(shù)。整個項目由這個函數(shù)調(diào)度使用。

創(chuàng)新互聯(lián)建站從2013年成立,先為鎮(zhèn)賚等服務(wù)建站,鎮(zhèn)賚等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為鎮(zhèn)賚企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
所以你的協(xié)程沒有被運行。
你將協(xié)程函數(shù)命名,在main函數(shù)中調(diào)用 go test()即可
相比很多其它流行語言,Go的語法相對簡潔。 此篇文章將介紹編程中常用的代碼元素,并展示一份簡單的Go程序代碼,以便讓剛開始學(xué)Go編程的程序員對Go代碼結(jié)構(gòu)有一個大概的印象。
編程和程序代碼元素
簡單來講,編程可以看作是以各種方式控制和組合計算機運行中的各種操作,以達(dá)到各種各樣的目的。 一個操作可能從一個硬件設(shè)備讀取、或者向一個硬件設(shè)備寫入一些數(shù)據(jù),從而完成一個特定的任務(wù)。 對于現(xiàn)代計算機來說,最基本的操作是底層計算機指令,比如CPU和GPU指令。 常見的硬件設(shè)備包括內(nèi)存、磁盤、網(wǎng)卡、顯卡,顯示器、鍵盤和鼠標(biāo)等。
直接操控底層計算機指令進(jìn)行編程是非常繁瑣和容易出錯的。 高級編程語言通過對底層指令進(jìn)行一些封裝和對數(shù)據(jù)進(jìn)行一些抽象,從而使得編程變得直觀和易于理解。
在流行高級編程語言中,一個操作通常是通過函數(shù)(function)調(diào)用或者使用操作符(operator)運算來完成的。 大多數(shù)高級編程語言都支持一些條件和循環(huán)控制語句。 這些條件和循環(huán)控制語句可以看作是特殊的操作。 它們的語法接近于人類語言,因此一個人寫的代碼很容易被其他人理解。
在大多數(shù)高級編程語言中,數(shù)據(jù)通常被抽象為各種類型(type)和值(value)。 一個類型可以看作是值的模板。一個值可以看作是某個類型的實例。 大多數(shù)編程語言支持自定義類型和若干預(yù)聲明類型(即內(nèi)置類型)。 一門語言的類型系統(tǒng)可以說是這門語言的靈魂。
編程中常常會使用大量的值。 一些在編碼階段可確定的值可以用它們的字面形式(literal,即字面量)來表示。 為了編程靈活和不易出錯,其它的值一般使用變量(variable)和(具名)常量(named constant)來表示。
在《Go語言101》中,具名的函數(shù)、具名的值(包括變量和具名常量)、以及定義類型和類型別名將被統(tǒng)稱為代碼要素。 代碼要素名必須為標(biāo)識符(identifier)。
高級編程語言代碼將被編譯器或者解釋器轉(zhuǎn)換為底層機器碼進(jìn)行執(zhí)行。 為了幫助編譯器和解釋器解析高級語言代碼,一些單詞將被用做關(guān)鍵字(keyword)。 這些單詞不能被當(dāng)做標(biāo)識符使用。
很多現(xiàn)代高級語言使用包(package)來組織代碼。 一個包必須引入(import)另一個包才能使用另一個包中的公有(導(dǎo)出的)代碼要素。 包名和包的引入名也都必須是標(biāo)識符。
盡管高級編程語言代碼比底層機器指令友好和易懂,我們還是需要一些注釋來幫助自己和其他程序員理解我們所寫的代碼。 在下一節(jié)的程序示例中,我們可以看到很多注釋。
一個簡單的Go示例程序
為了對各種代碼元素有一個更清楚的認(rèn)識,讓我們來看一個簡短的Go示例程序。 和很多其流行語言一樣,Go使用//來起始一個行注釋,使用一個/*和*/對來包裹一個塊注釋。
下面是這個Go示例程序。請注意閱讀其中的注釋。程序之后有更多解釋。
package main // 指定當(dāng)前源文件所在的包名
import "math/rand" // 引入一個標(biāo)準(zhǔn)庫包
const MaxRand = 16 // 聲明一個具名整型常量
// 一個函數(shù)聲明
/*
StatRandomNumbers生成一些不大于MaxRand的非負(fù)
隨機整數(shù),并統(tǒng)計和返回小于和大于MaxRand/2的隨機數(shù)
個數(shù)。輸入?yún)?shù)numRands指定了要生成的隨機數(shù)的總數(shù)。
*/
func StatRandomNumbers(numRands int) (int, int) {
// 聲明了兩個變量(類型都為int,初始值都為0)
var a, b int
// 一個for循環(huán)代碼塊
for i := 0; i numRands; i++ {
// 一個if-else條件控制代碼塊
if rand.Intn(MaxRand) MaxRand/2 {
a = a + 1
} else {
b++ // 等價于:b = b + 1
}
}
return a, b // 此函數(shù)返回兩個結(jié)果
}
// main函數(shù),或主函數(shù),是一個程序的入口函數(shù)。
func main() {
var num = 100
// 調(diào)用上面聲明的StatRandomNumbers函數(shù),
// 并將結(jié)果賦給使用短聲明語句聲明的兩個變量。
x, y := StatRandomNumbers(num)
// 調(diào)用兩個內(nèi)置函數(shù)(print和println)。
print("Result: ", x, " + ", y, " = ", num, "? ")
println(x+y == num)
}
將上面的程序代碼存盤到一個名為basic-code-element-demo.go 的文件中并使用下列命令運行此程序:
$ go run basic-code-element-demo.go
Result: 46 + 54 = 100? true
在上面的示例程序中,單詞package、import、const、func、var、for、if、else和return均為關(guān)鍵字。 其它大多數(shù)單詞均為標(biāo)識符。 請閱讀關(guān)鍵字和標(biāo)識符以獲得更多關(guān)于關(guān)鍵字和標(biāo)識符的信息。
四個int(一個在第15行,另三個在第13行) 表示內(nèi)置基本類型int。int類型是Go中的基本整數(shù)類型之一。 第5行中的16、第17行中的0、 第20行中的1以及第30行的100均為整型字面量。 第35行的"Result: "是一個字符串字面量。 請閱讀基本類型和它們的字面量表示以獲取更多關(guān)于基本類型和它們的字面量的信息。 Go中的非基本類型(均為組合類型)將在以后的其它文章中介紹和解釋。
第20行是一個賦值語句。 第5行聲明了一個具名常量,叫做MaxRand。 第15行和第30行使用標(biāo)準(zhǔn)變量聲明語句聲明了三個變量。 第17行的變量i以及第33行的變量x和y是使用變量短聲明語句聲明的。 變量a和b在聲明的時候被指定為int類型。 編譯器會自動推導(dǎo)出變量i、num、x和y的類型均為int類型,因為它們的初始值都是整型字面量表示的。 請閱讀常量和變量以獲取什么是類型不確定值、類型推導(dǎo)、賦值、以及如何聲明變量和具名常量。
上面的示例程序中使用了很多操作符,比如第17和19行的小于比較符,第36行的等于比較符==,還有第20和36行的加法運算符+。 第35行中的+不是一個運算符,它是一個字符串字面量中的一個字符。 一個使用操作符的操作中涉及到的值稱為操作值(有時也可稱為運算數(shù))。 請閱讀常用操作符以獲取更多關(guān)于操作符的信息。 更多操作符將在后續(xù)其它文章中介紹。
第35和36行調(diào)用了兩個內(nèi)置函數(shù)print和println。 從第13行到第26行聲明的函數(shù)StatRandomNumbers在第33行被調(diào)用。 第19行也調(diào)用了一個函數(shù) Intn。 這個函數(shù)聲明在math/rand標(biāo)準(zhǔn)庫包中。 請閱讀函數(shù)聲明及函數(shù)調(diào)用以獲取更多關(guān)于函數(shù)聲明及函數(shù)調(diào)用的信息。
(注意,一般print和println這兩個內(nèi)置函數(shù)并不推薦使用。 在正式的項目中,我們應(yīng)該盡量使用fmt標(biāo)準(zhǔn)庫包中聲明的相應(yīng)函數(shù)。 《Go語言101》只在開始的幾篇文章中使用了這兩個函數(shù)。)
第1行指定了當(dāng)前源文件所處的包的名稱。 一個Go程序的主函數(shù)(main函數(shù))必須被聲明在一個名稱為main的包中。 第3行引入了math/rand標(biāo)準(zhǔn)庫包,并以rand做為引入名。 在這個包中聲明的Intn函數(shù)將在第19行被調(diào)用。 請閱讀代碼包和包引入,以獲取更多關(guān)于代碼包和包引入的信息。
表達(dá)式、語句和簡單語句一文中介紹了什么是表達(dá)式和語句。特別地,此文列出了所有的簡單語句類型。 在Go代碼中,各種流程控制代碼塊中的某些部分必須為簡單語句,某些部分必須為表達(dá)式。
StatRandomNumbers函數(shù)的聲明體中使用了兩個流程控制代碼塊。 其中一個是for循環(huán)代碼塊,它內(nèi)嵌了另外一個代碼塊。 另外一個代碼塊是一個if-else條件控制代碼塊。 請閱讀基本流程控制語法以獲取更多關(guān)于流程控制代碼塊的信息。 更多的特殊的流程控制代碼塊將在以后的其它文章中介紹。
空行常常用來增加代碼的可讀性。 上面的程序中也包涵了很多注釋,但它們大多是為了Go初學(xué)者快速理解的目的而加入的。 我們應(yīng)該盡量使代碼自解釋,只在確實需要解釋的地方進(jìn)行注釋。
關(guān)于代碼斷行
像很多其它流行編程語言一樣,Go也使用一對大括號{ and }來形成一個顯式代碼塊。但是在Go代碼中,編碼樣式風(fēng)格有一些限制。 比如,很多左大括號{不能被放到下一行。 如果,上面的StatRandomNumbers被修改成如下所示,則上面的示例程序?qū)⒕幾g不通過。
func StatRandomNumbers(numRands int) (int, int)
{ // 編譯錯誤:語法錯誤
var a, b int
for i := 0; i numRands; i++
{ // 編譯錯誤:語法錯誤
if rand.Intn(MaxRand) MaxRand/2
{ // 編譯錯誤:語法錯誤
a = a + 1
} else {
b++
}
}
return a, b
}
一些程序員不是很喜歡這些限制。但是這些限制有兩個好處:
它們使得Go程序編譯得非??臁?/p>
它們使得不同的Go程序員編寫的代碼風(fēng)格類似,從而一個Go程序員寫的代碼很容易被另一個程序員看懂。
我們可以閱讀代碼斷行規(guī)則一文以獲取更多關(guān)于代碼換行規(guī)則的細(xì)節(jié)。在目前,我們最好避免將左大括號放在下一行。 或者說,每行的非空起始字符不能是左大括號(但是,請記住,這不是一個普適的規(guī)則
import "workname/packetfolder"
導(dǎo)入多個包
方法調(diào)用 包名.函數(shù)//不是函數(shù)或結(jié)構(gòu)體所處文件或文件夾名
packagename.Func()
前面加個點表示省略調(diào)用,那么調(diào)用該模塊里面的函數(shù),可以不用寫模塊名稱了:
當(dāng)導(dǎo)入一個包時,該包下的文件里所有init()函數(shù)都會被執(zhí)行,然而,有些時候我們并不需要把整個包都導(dǎo)入進(jìn)來,僅僅是是希望它執(zhí)行init()函數(shù)而已。下劃線的作用僅僅是為了調(diào)用init()函數(shù),所以無法通過包名來調(diào)用包中的其他函數(shù)
import _ package
變量聲明必須要使用否則會報錯。
全局變量運行聲明但不使用。
func 函數(shù)名 (參數(shù)1,參數(shù)2,...) (返回值a 類型a, 返回值b 類型b,...)
func 函數(shù)名 (參數(shù)1,參數(shù)2,...) (返回值類型1, 返回值類型2,...)
func (this *結(jié)構(gòu)體名) 函數(shù)名(參數(shù) string) (返回值類型1, 返回值類型2){}
使用大小來區(qū)分函數(shù)可見性
大寫是public類型
小寫是private類型
func prifunc int{}
func pubfunc int{}
聲明靜態(tài)變量
const value int
定義變量
var value int
聲明一般類型、接口和結(jié)構(gòu)體
聲明函數(shù)
func function () int{}
go里面所有的空值對應(yīng)如下
通道類型
內(nèi)建函數(shù) new 用來分配內(nèi)存,它的第一個參數(shù)是一個類型,不是一個值,它的返回值是一個指向新分配類型零值的指針
func new(Type) *Type
[這位博主有非常詳細(xì)的分析]
Go 語言支持并發(fā),我們只需要通過 go 關(guān)鍵字來開啟 goroutine 即可。
goroutine 是輕量級線程,goroutine 的調(diào)度是由 Golang 運行時進(jìn)行管理的。
同一個程序中的所有 goroutine 共享同一個地址空間。
語法格式如下:
通道(channel)是用來傳遞數(shù)據(jù)的一個數(shù)據(jù)結(jié)構(gòu)。
通道的聲明
通道可用于兩個 goroutine 之間通過傳遞一個指定類型的值來同步運行和通訊。操作符 - 用于指定通道的方向,發(fā)送或接收。如果未指定方向,則為雙向通道。
[這里有比較詳細(xì)的用例]
go里面的空接口可以指代任何類型(無論是變量還是函數(shù))
聲明空接口
go里面的的強制類型轉(zhuǎn)換語法為:
int(data)
如果是接口類型的強制轉(zhuǎn)成其他類型的語法為:
go里面的強制轉(zhuǎn)換是將值復(fù)制過去,所以在數(shù)據(jù)量的時候有比較高的運行代價
GO語言的優(yōu)勢:可直接編譯成機器碼,不依賴其他庫,glibc的版本有一定要求,部署就是扔一個文件上去就完成了。靜態(tài)類型語言,但是有動態(tài)語言的感覺,靜態(tài)類型的語言就是可以在編譯的時候檢查出來隱藏的大多數(shù)問題,動態(tài)語言的感覺就是有很多的包可以使用,寫起來的效率很高。語言層面支持并發(fā),這個就是Go最大的特色,天生的支持并發(fā),我曾經(jīng)說過一句話,天生的基因和整容是有區(qū)別的,大家一樣美麗,但是你喜歡整容的還是天生基因的美麗呢?Go就是基因里面支持的并發(fā),可以充分的利用多核,很容易的使用并發(fā)。內(nèi)置runtime,支持垃圾回收,這屬于動態(tài)語言的特性之一吧,雖然目前來說GC不算完美,但是足以應(yīng)付我們所能遇到的大多數(shù)情況,特別是Go1.1之后的GC。簡單易學(xué),Go語言的作者都有C的基因,那么Go自然而然就有了C的基因,那么Go關(guān)鍵字是25個,但是表達(dá)能力很強大,幾乎支持大多數(shù)你在其他語言見過的特性:繼承、重載、對象等。豐富的標(biāo)準(zhǔn)庫,Go目前已經(jīng)內(nèi)置了大量的庫,特別是網(wǎng)絡(luò)庫非常強大,我最愛的也是這部分。內(nèi)置強大的工具,Go語言里面內(nèi)置了很多工具鏈,最好的應(yīng)該是gofmt工具,自動化格式化代碼,能夠讓團隊review變得如此的簡單,代碼格式一模一樣,想不一樣都很困難。跨平臺編譯,如果你寫的Go代碼不包含cgo,那么就可以做到window系統(tǒng)編譯linux的應(yīng)用,如何做到的呢?Go引用了plan9的代碼,這就是不依賴系統(tǒng)的信息。Go語言這么多的優(yōu)勢,你還不想學(xué)嗎?我記得當(dāng)時我看的是黑馬程序員的視頻,我對他們視頻的印象就是通俗易懂,就是好!
GO是編譯性語言,所以函數(shù)的順序是無關(guān)緊要的,為了方便閱讀,建議入口函數(shù) main 寫在最前面,其余函數(shù)按照功能需要進(jìn)行排列
GO的函數(shù) 不支持嵌套,重載和默認(rèn)參數(shù)
GO的函數(shù) 支持 無需聲明變量,可變長度,多返回值,匿名,閉包等
GO的函數(shù)用 func 來聲明,且左大括號 { 不能另起一行
一個簡單的示例:
輸出為:
參數(shù):可以傳0個或多個值來供自己用
返回:通過用 return 來進(jìn)行返回
輸出為:
上面就是一個典型的多參數(shù)傳遞與多返回值
對例子的說明:
按值傳遞:是對某個變量進(jìn)行復(fù)制,不能更改原變量的值
引用傳遞:相當(dāng)于按指針傳遞,可以同時改變原來的值,并且消耗的內(nèi)存會更少,只有4或8個字節(jié)的消耗
在上例中,返回值 (d int, e int, f int) { 是進(jìn)行了命名,如果不想命名可以寫成 (int,int,int){ ,返回的結(jié)果都是一樣的,但要注意:
當(dāng)返回了多個值,我們某些變量不想要,或?qū)嶋H用不到,我們可以使用 _ 來補位,例如上例的返回我們可以寫成 d,_,f := test(a,b,c) ,我們不想要中間的返回值,可以以這種形式來舍棄掉
在參數(shù)后面以 變量 ... type 這種形式的,我們就要以判斷出這是一個可變長度的參數(shù)
輸出為:
在上例中, strs ...string 中, strs 的實際值是b,c,d,e,這就是一個最簡單的傳遞可變長度的參數(shù)的例子,更多一些演變的形式,都非常類似
在GO中 defer 關(guān)鍵字非常重要,相當(dāng)于面相對像中的析構(gòu)函數(shù),也就是在某個函數(shù)執(zhí)行完成后,GO會自動這個;
如果在多層循環(huán)中函數(shù)里,都定義了 defer ,那么它的執(zhí)行順序是先進(jìn)后出;
當(dāng)某個函數(shù)出現(xiàn)嚴(yán)重錯誤時, defer 也會被調(diào)用
輸出為
這是一個最簡單的測試了,當(dāng)然還有更復(fù)雜的調(diào)用,比如調(diào)試程序時,判斷是哪個函數(shù)出了問題,完全可以根據(jù) defer 打印出來的內(nèi)容來進(jìn)行判斷,非常快速,這種留給你們?nèi)崿F(xiàn)
一個函數(shù)在函數(shù)體內(nèi)自己調(diào)用自己我們稱之為遞歸函數(shù),在做遞歸調(diào)用時,經(jīng)常會將內(nèi)存給占滿,這是非常要注意的,常用的比如,快速排序就是用的遞歸調(diào)用
本篇重點介紹了GO函數(shù)(func)的聲明與使用,下一篇將介紹GO的結(jié)構(gòu) struct