日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

go基础系列:简介

發(fā)布時(shí)間:2025/5/22 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go基础系列:简介 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.Go簡(jiǎn)介

Go語(yǔ)言是編譯型、靜態(tài)類(lèi)型的類(lèi)C的語(yǔ)言,并帶有GC(垃圾收集器,garbage collection)。這意味著什么?

另外,Go是一種非常嚴(yán)格的語(yǔ)言,它幾乎總是要求我們"以標(biāo)準(zhǔn)答案去答題",在其它語(yǔ)言可以容忍的不規(guī)范編碼方式在Go語(yǔ)言中幾乎都會(huì)拋異常。例如導(dǎo)入了包卻沒(méi)有使用這個(gè)包,Go不會(huì)去編譯它并報(bào)錯(cuò)。再例如,定義了一個(gè)變量但從來(lái)沒(méi)用過(guò),也會(huì)報(bào)錯(cuò)。

初學(xué)Go的時(shí)候,這可能是件無(wú)比的苦惱事情,但習(xí)慣了之后,編寫(xiě)出來(lái)的程序自然是無(wú)比規(guī)范的。這也正是Go和不少語(yǔ)言的區(qū)別:其它語(yǔ)言編碼、調(diào)試階段可能很快,但維護(hù)和優(yōu)化階段可能會(huì)非常長(zhǎng);而Go的編碼周期可能稍長(zhǎng),但編碼完成后幾乎都是足夠優(yōu)化的,維護(hù)和優(yōu)化周期足夠短。

編譯型

編譯表示的是將你所寫(xiě)的源代碼轉(zhuǎn)換為低層次的語(yǔ)言,例如匯編語(yǔ)言(go采用此底層語(yǔ)言),或者其它中間的語(yǔ)言(如Java、C#編譯成字節(jié)碼)。

編譯型語(yǔ)言可能不太友好,因?yàn)榫幾g的過(guò)程速度很慢。如果一個(gè)程序的編譯過(guò)程就需要花幾分鐘甚至幾小時(shí),那么程序的版本迭代可能會(huì)很難進(jìn)行下去。編譯速度是Go語(yǔ)言的一個(gè)主要設(shè)計(jì)目標(biāo),值得慶幸的是,Go的編譯速度很快,即便對(duì)于習(xí)慣于使用解釋型語(yǔ)言的人來(lái)說(shuō),它也還是快。

編譯型語(yǔ)言雖然編譯過(guò)程慢,但這類(lèi)語(yǔ)言在運(yùn)行階段可能會(huì)更快,而且運(yùn)行時(shí)不再需要加載額外的依賴(lài)。

靜態(tài)類(lèi)型

靜態(tài)語(yǔ)言意味著變量必須要指定數(shù)據(jù)類(lèi)型(int,string,bool,[]byte等)。雖然必須指定數(shù)據(jù)類(lèi)型,但除了在聲明變量的時(shí)候顯式指定數(shù)據(jù)類(lèi)型,也可以讓Go自己去推斷數(shù)據(jù)類(lèi)型(稍后有示例)。

對(duì)于習(xí)慣于使用動(dòng)態(tài)型語(yǔ)言的人來(lái)說(shuō),可能會(huì)感覺(jué)靜態(tài)型語(yǔ)言很笨重,事實(shí)確實(shí)如此。但靜態(tài)有靜態(tài)的好處,特別是配合編譯操作的時(shí)候。

關(guān)于靜態(tài)和動(dòng)態(tài)數(shù)據(jù)類(lèi)型,要說(shuō)的內(nèi)容其實(shí)很多很多,畢竟對(duì)于一門(mén)語(yǔ)言來(lái)說(shuō),數(shù)據(jù)類(lèi)型牽一發(fā)而動(dòng)全身,無(wú)論是靜態(tài)、還是動(dòng)態(tài)型語(yǔ)言,都因此而衍生出無(wú)數(shù)的優(yōu)、缺點(diǎn)。

類(lèi)C型的語(yǔ)言

當(dāng)我們說(shuō)一門(mén)語(yǔ)言是類(lèi)C型(C-like)的語(yǔ)言時(shí),意味著這門(mén)語(yǔ)言里有一些語(yǔ)法和特性和C語(yǔ)言是類(lèi)似的。例如,&&表示布爾的AND,==表示等值比較,數(shù)組索引從0開(kāi)始計(jì)算,{...}表示一段代碼塊,也表示它屬于一個(gè)作用域范圍,等等。

類(lèi)C型語(yǔ)言也意味著每行的語(yǔ)句要使用分號(hào)";"結(jié)束,條件表達(dá)式要使用括號(hào)包圍。但Go語(yǔ)言不采用這兩種方式,盡管還是可以使用括號(hào)包圍條件表達(dá)式以改變優(yōu)先級(jí)。例如:

if name == "malongshuai" {print("name rigth!") }

一個(gè)更復(fù)雜一點(diǎn)的條件表達(dá)式,使用括號(hào)改變優(yōu)先級(jí):

if (name == "longshuai" && age > 23) || (name == "xiaofang" && age < 22) {print("yeyeye!!!") }

GC

每當(dāng)創(chuàng)建一個(gè)變量后,這個(gè)變量都會(huì)有其生命周期。例如,函數(shù)內(nèi)部的本地變量將在函數(shù)退出的時(shí)候消逝。對(duì)于非函數(shù)內(nèi)部的變量生命周期,無(wú)論是對(duì)程序員還是對(duì)編譯器來(lái)說(shuō),變量的生命周期都沒(méi)有那么顯而易見(jiàn)。

沒(méi)有g(shù)arbage collection,意味著要讓程序員自己來(lái)決定變量所占用內(nèi)存的釋放,這是很艱巨的任務(wù),而且很容易出錯(cuò)導(dǎo)致程序崩潰。

帶有GC的語(yǔ)言可以對(duì)變量進(jìn)行跟蹤,并且在它們不再被需要的時(shí)候自動(dòng)釋放它們。雖然GC帶來(lái)了一點(diǎn)點(diǎn)的負(fù)載,會(huì)影響一點(diǎn)點(diǎn)的性能,但對(duì)于現(xiàn)在高性能的計(jì)算機(jī)來(lái)說(shuō),這點(diǎn)影響相比它帶來(lái)的優(yōu)點(diǎn)而言,完全可以將其無(wú)視。

嘗試寫(xiě)一個(gè)簡(jiǎn)單的Go程序

按照國(guó)際管理,每一門(mén)語(yǔ)言總是以hello world開(kāi)篇。這里就算了,因?yàn)槲矣形业膽T例。

先安裝Go,so easy...

目前還沒(méi)有必要涉及Go的工作空間,所以隨意找個(gè)地方創(chuàng)建一個(gè)test.go文件,內(nèi)容如下:

package mainfunc main() {println("Let's Go") }

然后運(yùn)行:

go run test.go

顯然,它將輸出Let's Go。但是Go的編譯過(guò)程呢?go run命令同時(shí)進(jìn)行了編譯和運(yùn)行兩個(gè)過(guò)程:它將使用一個(gè)臨時(shí)目錄保存構(gòu)建的程序,然后執(zhí)行它,最后自動(dòng)清理構(gòu)建出來(lái)的臨時(shí)程序。

可以使用go run --work查看下具體情況:

$ go run --work test.go WORK=/tmp/go-build267589647 Let's Go

構(gòu)建的臨時(shí)目錄位于/tmp/go-buildXXXX中(我這是Linux),在此目錄下會(huì)有一個(gè)二進(jìn)制程序(對(duì)于Windows則是.exe文件):

$ tree /tmp/go-build267589647/ /tmp/go-build267589647/ ├── command-line-arguments │?? └── _obj │?? └── exe │?? └── test # 這是可執(zhí)行二進(jìn)制程序 └── command-line-arguments.a

那個(gè)test文件就是編譯后得到的二進(jìn)制程序,可以直接用來(lái)執(zhí)行:

$ /tmp/go-build267589647/command-line-arguments/_obj/exe/test Let's Go

如果要顯式編譯,使用go build命令:

go build test.go

它將在當(dāng)前目錄下生成一個(gè)名為test的二進(jìn)制文件,可以直接拿來(lái)運(yùn)行,就像前面/tmp中的一樣。

$ ./tese Let's Go

在開(kāi)發(fā)階段,用go build還是用go run,隨意即可。但在部署的時(shí)候,一般先go build,再go run。

main包和main函數(shù)

在上面的代碼中,聲明了這個(gè)包的名稱(chēng)為main,然后創(chuàng)建一個(gè)函數(shù),并在此函數(shù)中使用println輸出了一個(gè)字符串,但是go run如何知道要去執(zhí)行什么?在Go中,程序的入口是main包中的main函數(shù),這兩名稱(chēng)都是固定的。

對(duì)于一個(gè)從沒(méi)編程過(guò)的人,可能不理解程序的入口。它表示程序從此處開(kāi)始執(zhí)行,函數(shù)main中可能會(huì)包含很多其它函數(shù)的調(diào)用,這些函數(shù)可能放在其它文件(包)中。通過(guò)一次次、一層層的調(diào)用,從而將整個(gè)程序的所有代碼、邏輯都連接在一起并運(yùn)行。

如果你愿意,可以試著修改一下package后面的main關(guān)鍵字,然后go run和go build都運(yùn)行一下。再試著修改一下func main的main關(guān)鍵字,go run和go build再運(yùn)行一下。

關(guān)于包的內(nèi)容,后面再做介紹。目前來(lái)說(shuō),需要理解的只是些基礎(chǔ),對(duì)于基礎(chǔ)階段來(lái)說(shuō),我們將總是在main包中寫(xiě)代碼。

import

Go有一些內(nèi)置的函數(shù),例如上面的println,內(nèi)置函數(shù)無(wú)需額外的引用就可直接調(diào)用。但內(nèi)置函數(shù)畢竟很少,所以得從已經(jīng)寫(xiě)好的Go標(biāo)準(zhǔn)庫(kù)和其它第三方庫(kù)中找出一些工具來(lái)使用。

在Go中,import關(guān)鍵字用于定義要導(dǎo)入到當(dāng)前文件的包名,導(dǎo)入某個(gè)包后,這個(gè)包中的屬性就能在當(dāng)前文件中去訪問(wèn),例如調(diào)用屬于這個(gè)包的函數(shù)。

例如,將前面的代碼改改:

package mainimport ("fmt""os" )func main (){if len(os.Args) != 2{os.Exit(1)}fmt.Println("Arg0: ",os.Args[0])fmt.Println("Arg1: ",os.Args[1]) }

執(zhí)行一下:

$ go run test.go exit status 1$ go run test.go a b exit status 1$ go run test.go a Arg0: /tmp/go-build730099388/command-line-arguments/_obj/exe/test Arg1: a

上面的import導(dǎo)入了兩個(gè)標(biāo)準(zhǔn)包:fmt和os,還使用了另一個(gè)內(nèi)置函數(shù)len()。

len()函數(shù)返回字符串的長(zhǎng)度、字典的元素個(gè)數(shù)以及數(shù)組的元素個(gè)數(shù)。上面使用len()判斷了該Go程序的參數(shù)個(gè)數(shù)必須為2,否則就以狀態(tài)碼1退出該程序。看上面的運(yùn)行結(jié)果,好像只有給一個(gè)參數(shù)的時(shí)候才是正確的,這是因?yàn)榈谝粋€(gè)參數(shù)(Args[0])代表的總是當(dāng)前正在運(yùn)行的程序名稱(chēng),正如上面結(jié)果所顯示的那樣。

你可能還注意到了fmt.Println,前綴fmt正好是導(dǎo)入的一個(gè)包名,這表示使用fmt包中的Println函數(shù)。

本文的開(kāi)頭就說(shuō)過(guò)了,Go是一門(mén)非常嚴(yán)格的語(yǔ)言,如果這里導(dǎo)入了fmt包,但卻沒(méi)有使用它,它將報(bào)錯(cuò)。

# command-line-arguments ./test.go:4:5: imported and not used: "fmt"

關(guān)于Go文檔

關(guān)于fmt的Println函數(shù)詳細(xì)用法,可去參考Go的官方文檔:https://golang.org/pkg/fmt/#Println。當(dāng)然,現(xiàn)階段去看官方手冊(cè),那是在找死。

還可以使用go doc命令去查找各幫助文檔。

例如,查看fmt包的幫助文檔:

go doc fmt

查看fmt.Println函數(shù)的用法:

go doc fmt.Println

完整用法:

go doc go doc <pkg> go doc <sym>[.<method>] go doc [<pkg>].<sym>[.<method>] go doc <pkg> <sym>[.<method>]

此外,還可以構(gòu)建本地的網(wǎng)頁(yè)版官方手冊(cè),在斷網(wǎng)的時(shí)候可以訪問(wèn):

godoc -http=:6060

然后就可以在瀏覽器中通過(guò)http://localhost:6060/訪問(wèn)官方手冊(cè)。

變量和變量聲明

很多語(yǔ)言中,要為變量賦值只需一個(gè)語(yǔ)句:

x=10

這個(gè)語(yǔ)句中實(shí)際上包含了兩個(gè)過(guò)程:變量的聲明和變量的賦值。聲明一般也被稱(chēng)為"定義"。

在Go中,必須先聲明變量,再賦值或使用變量。最復(fù)雜的聲明+賦值操作為:

package mainimport ( "fmt" )func main(){var x intx=10fmt.Println("x =",x) }

此處聲明了一個(gè)變量x,其數(shù)據(jù)類(lèi)型為int。默認(rèn)情況下,Go在變量的聲明期間會(huì)為其做初始化賦值:int類(lèi)型初始化賦值為0,booleans初始化賦值為false,strings初始化賦值為"",等等。

可以將聲明和賦值操作合并:

var x int = 10

還有一種更方便的聲明+賦值方式:

x := 10

通過(guò)這種變量的定義方式,還可以將函數(shù)執(zhí)行結(jié)果(返回值)賦值給變量。例如:

func main() {x := getAdd(10) }func getAdd(x int) int {return x+1 }

:=在Go中屬于類(lèi)型推斷操作,它包含了變量聲明和變量賦值兩個(gè)過(guò)程。

需要注意的是,變量聲明之后不能再次聲明(除非在不同的作用域),之后只能使用=進(jìn)行賦值。例如,執(zhí)行下面的代碼將報(bào)錯(cuò):

package mainimport ("fmt")func main(){x:=10fmt.Println("x =",x)x:=11fmt.Println("x =",x) }

錯(cuò)誤如下:

# command-line-arguments .\test.go:8:3: no new variables on left side of :=

報(bào)錯(cuò)信息很明顯,:=左邊沒(méi)有新變量。

如果仔細(xì)看上面的報(bào)錯(cuò)信息,會(huì)發(fā)現(xiàn)no new variables是一個(gè)復(fù)數(shù)。實(shí)際上,Go允許我們使用:=一次性聲明、賦值多個(gè)變量,而且只要左邊有任何一個(gè)新變量,語(yǔ)法就是正確的。

func main(){name,age := "longshuai",23fmt.Println("name:",name,"age:",age)// name重新賦值,因?yàn)橛幸粋€(gè)新變量weightweight,name := 90,"malongshuai"fmt.Println("name:",name,"weight:",weight) }

需要注意,name第二次被:=賦值,Go第一次推斷出該變量的數(shù)據(jù)類(lèi)型之后,就不允許:=再改變它的數(shù)據(jù)類(lèi)型,因?yàn)橹挥械谝淮?=對(duì)name進(jìn)行聲明,之后所有的:=對(duì)name都只是簡(jiǎn)單的賦值操作。

例如,下面將報(bào)錯(cuò):

weight,name := 90,80

錯(cuò)誤信息:

.\test.go:11:14: cannot use 80 (type int) as type string in assignment

另外,變量聲明之后必須使用,否則會(huì)報(bào)錯(cuò),因?yàn)镚o對(duì)規(guī)范的要求非常嚴(yán)格。例如,下面定義了weight但卻沒(méi)使用:

weight,name := 90,"malongshuai" fmt.Println("name:",name)

錯(cuò)誤信息:

.\test.go:11:2: weight declared and not used

函數(shù)定義

Go的函數(shù)允許有多個(gè)返回值。例如:

// 該函數(shù)有一個(gè)參數(shù),沒(méi)有返回值 func log(message string){...CODE... }// 該函數(shù)有兩個(gè)參數(shù),一個(gè)返回值,返回值的類(lèi)型為int func add(a int,b int) int {...CODE... }// 該函數(shù)一個(gè)參數(shù),兩個(gè)返回值,分別是int和bool func power(name string) (int,bool) {...CODE... }

既然函數(shù)可以有返回值,就可以將其返回值賦值給變量:

value, exists := power("malongshuai") if exists == false {...CODE... }

有些時(shí)候,我們可能并不需要所有的返回值。例如,我們只想要取得power()的第二個(gè)返回值。這時(shí)可以將不想要的返回值丟給特殊符號(hào)下劃線_,它表示丟棄這部分結(jié)果。

_,exists := power("longshuai") if exists == false {...CODE... }

如果函數(shù)的參數(shù)類(lèi)型相同,則不同的參數(shù)可以共享數(shù)據(jù)類(lèi)型。

func (a,b int) int {...CODE... }

轉(zhuǎn)載于:https://www.cnblogs.com/f-ck-need-u/p/9832577.html

總結(jié)

以上是生活随笔為你收集整理的go基础系列:简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。