本文介紹一些Go語言的基礎(chǔ)語法。
為佛坪等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及佛坪網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站建設(shè)、成都網(wǎng)站制作、佛坪網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
先來看一個簡單的go語言代碼:
go語言的注釋方法:
代碼執(zhí)行結(jié)果:
下面來進一步介紹go的基礎(chǔ)語法。
go語言中格式化輸出可以使用 fmt 和 log 這兩個標(biāo)準(zhǔn)庫,
常用方法:
示例代碼:
執(zhí)行結(jié)果:
更多格式化方法可以訪問中的fmt包。
log包實現(xiàn)了簡單的日志服務(wù),也提供了一些格式化輸出的方法。
執(zhí)行結(jié)果:
下面來介紹一下go的數(shù)據(jù)類型
下表列出了go語言的數(shù)據(jù)類型:
int、float、bool、string、數(shù)組和struct屬于值類型,這些類型的變量直接指向存在內(nèi)存中的值;slice、map、chan、pointer等是引用類型,存儲的是一個地址,這個地址存儲最終的值。
常量是在程序編譯時就確定下來的值,程序運行時無法改變。
執(zhí)行結(jié)果:
執(zhí)行結(jié)果:
Go 語言的運算符主要包括算術(shù)運算符、關(guān)系運算符、邏輯運算符、位運算符、賦值運算符以及指針相關(guān)運算符。
算術(shù)運算符:
關(guān)系運算符:
邏輯運算符:
位運算符:
賦值運算符:
指針相關(guān)運算符:
下面介紹一下go語言中的if語句和switch語句。另外還有一種控制語句叫select語句,通常與通道聯(lián)用,這里不做介紹。
if語法格式如下:
if ... else :
else if:
示例代碼:
語法格式:
另外,添加 fallthrough 會強制執(zhí)行后面的 case 語句,不管下一條case語句是否為true。
示例代碼:
執(zhí)行結(jié)果:
下面介紹幾種循環(huán)語句:
執(zhí)行結(jié)果:
執(zhí)行結(jié)果:
也可以通過標(biāo)記退出循環(huán):
--THE END--
很多朋友可能知道Go語言的優(yōu)勢在哪,卻不知道Go語言適合用于哪些地方。
1、 Go語言作為服務(wù)器編程語言,很適合處理日志、數(shù)據(jù)打包、虛擬機處理、文件系統(tǒng)、分布式系統(tǒng)、數(shù)據(jù)庫代理等;網(wǎng)絡(luò)編程方面。Go語言廣泛應(yīng)用于Web應(yīng)用、API應(yīng)用、下載應(yīng)用等;除此之外,Go語言還可用于內(nèi)存數(shù)據(jù)庫和云平臺領(lǐng)域,目前國外很多云平臺都是采用Go開發(fā)。
2、 其實Go語言主要用作服務(wù)器端開發(fā)。其定位是用來開發(fā)"大型軟件"的,適合于很多程序員一起開發(fā)大型軟件,并且開發(fā)周期長,支持云計算的網(wǎng)絡(luò)服務(wù)。Go語言能夠讓程序員快速開發(fā),并且在軟件不斷的增長過程中,它能讓程序員更容易地進行維護和修改。它融合了傳統(tǒng)編譯型語言的高效性和腳本語言的易用性和富于表達性。
3、 Go語言成功案例。Nsq:Nsq是由Go語言開發(fā)的高性能、高可用消息隊列系統(tǒng),性能非常高,每天能處理數(shù)十億條的消息;
4、 Docker:基于lxc的一個虛擬打包工具,能夠?qū)崿F(xiàn)PAAS平臺的組建。
5、 Packer:用來生成不同平臺的鏡像文件,例如VM、vbox、AWS等,作者是vagrant的作者
6、 Skynet:分布式調(diào)度框架。
7、 Doozer:分布式同步工具,類似ZooKeeper。
8、 Heka:mazila開源的日志處理系統(tǒng)。
9、 Cbfs:couchbase開源的分布式文件系統(tǒng)。
10、 Tsuru:開源的PAAS平臺,和SAE實現(xiàn)的功能一模一樣。
11、 Groupcache:memcahe作者寫的用于Google下載系統(tǒng)的緩存系統(tǒng)。
12、 God:類似redis的緩存系統(tǒng),但是支持分布式和擴展性。
13、 Gor:網(wǎng)絡(luò)流量抓包和重放工具。
以上的就是關(guān)于go語言能做什么的內(nèi)容介紹了。
Go語言中沒有“類”的概念,也不支持“類”的繼承等面向?qū)ο蟮母拍?。Go語言中通過結(jié)構(gòu)體的內(nèi)嵌再配合接口比面向?qū)ο缶哂懈叩臄U展性和靈活性。
自定義類型
在Go語言中有一些基本的數(shù)據(jù)類型,如string、整型、浮點型、布爾等數(shù)據(jù)類型, Go語言中可以使用type關(guān)鍵字來定義自定義類型。
自定義類型是定義了一個全新的類型。我們可以基于內(nèi)置的基本類型定義,也可以通過struct定義。例如:
通過Type關(guān)鍵字的定義,MyInt就是一種新的類型,它具有int的特性。
類型別名
類型別名是Go1.9版本添加的新功能。
類型別名規(guī)定:TypeAlias只是Type的別名,本質(zhì)上TypeAlias與Type是同一個類型。就像一個孩子小時候有小名、乳名,上學(xué)后用學(xué)名,英語老師又會給他起英文名,但這些名字都指的是他本人。
type TypeAlias = Type
我們之前見過的rune和byte就是類型別名,他們的定義如下:
類型定義和類型別名的區(qū)別
類型別名與類型定義表面上看只有一個等號的差異,我們通過下面的這段代碼來理解它們之間的區(qū)別。
結(jié)果顯示a的類型是main.NewInt,表示main包下定義的NewInt類型。b的類型是int。MyInt類型只會在代碼中存在,編譯完成時并不會有MyInt類型。
Go語言中的基礎(chǔ)數(shù)據(jù)類型可以表示一些事物的基本屬性,但是當(dāng)我們想表達一個事物的全部或部分屬性時,這時候再用單一的基本數(shù)據(jù)類型明顯就無法滿足需求了,Go語言提供了一種自定義數(shù)據(jù)類型,可以封裝多個基本數(shù)據(jù)類型,這種數(shù)據(jù)類型叫結(jié)構(gòu)體,英文名稱struct。 也就是我們可以通過struct來定義自己的類型了。
Go語言中通過struct來實現(xiàn)面向?qū)ο蟆?/p>
結(jié)構(gòu)體的定義
使用type和struct關(guān)鍵字來定義結(jié)構(gòu)體,具體代碼格式如下:
其中:
舉個例子,我們定義一個Person(人)結(jié)構(gòu)體,代碼如下:
同樣類型的字段也可以寫在一行,
這樣我們就擁有了一個person的自定義類型,它有name、city、age三個字段,分別表示姓名、城市和年齡。這樣我們使用這個person結(jié)構(gòu)體就能夠很方便的在程序中表示和存儲人信息了。
語言內(nèi)置的基礎(chǔ)數(shù)據(jù)類型是用來描述一個值的,而結(jié)構(gòu)體是用來描述一組值的。比如一個人有名字、年齡和居住城市等,本質(zhì)上是一種聚合型的數(shù)據(jù)類型
結(jié)構(gòu)體實例化
只有當(dāng)結(jié)構(gòu)體實例化時,才會真正地分配內(nèi)存。也就是必須實例化后才能使用結(jié)構(gòu)體的字段。
基本實例化
舉個例子:
我們通過.來訪問結(jié)構(gòu)體的字段(成員變量),例如p1.name和p1.age等。
匿名結(jié)構(gòu)體
在定義一些臨時數(shù)據(jù)結(jié)構(gòu)等場景下還可以使用匿名結(jié)構(gòu)體。
創(chuàng)建指針類型結(jié)構(gòu)體
我們還可以通過使用new關(guān)鍵字對結(jié)構(gòu)體進行實例化,得到的是結(jié)構(gòu)體的地址。 格式如下:
從打印的結(jié)果中我們可以看出p2是一個結(jié)構(gòu)體指針。
需要注意的是在Go語言中支持對結(jié)構(gòu)體指針直接使用.來訪問結(jié)構(gòu)體的成員。
取結(jié)構(gòu)體的地址實例化
使用對結(jié)構(gòu)體進行取地址操作相當(dāng)于對該結(jié)構(gòu)體類型進行了一次new實例化操作。
p3.name = "七米"其實在底層是(*p3).name = "七米",這是Go語言幫我們實現(xiàn)的語法糖。
結(jié)構(gòu)體初始化
沒有初始化的結(jié)構(gòu)體,其成員變量都是對應(yīng)其類型的零值。
使用鍵值對初始化
使用鍵值對對結(jié)構(gòu)體進行初始化時,鍵對應(yīng)結(jié)構(gòu)體的字段,值對應(yīng)該字段的初始值。
也可以對結(jié)構(gòu)體指針進行鍵值對初始化,例如:
當(dāng)某些字段沒有初始值的時候,該字段可以不寫。此時,沒有指定初始值的字段的值就是該字段類型的零值。
使用值的列表初始化
初始化結(jié)構(gòu)體的時候可以簡寫,也就是初始化的時候不寫鍵,直接寫值:
使用這種格式初始化時,需要注意:
結(jié)構(gòu)體內(nèi)存布局
結(jié)構(gòu)體占用一塊連續(xù)的內(nèi)存。
輸出:
【進階知識點】關(guān)于Go語言中的內(nèi)存對齊推薦閱讀:在 Go 中恰到好處的內(nèi)存對齊
面試題
請問下面代碼的執(zhí)行結(jié)果是什么?
構(gòu)造函數(shù)
Go語言的結(jié)構(gòu)體沒有構(gòu)造函數(shù),我們可以自己實現(xiàn)。 例如,下方的代碼就實現(xiàn)了一個person的構(gòu)造函數(shù)。 因為struct是值類型,如果結(jié)構(gòu)體比較復(fù)雜的話,值拷貝性能開銷會比較大,所以該構(gòu)造函數(shù)返回的是結(jié)構(gòu)體指針類型。
調(diào)用構(gòu)造函數(shù)
方法和接收者
Go語言中的方法(Method)是一種作用于特定類型變量的函數(shù)。這種特定類型變量叫做接收者(Receiver)。接收者的概念就類似于其他語言中的this或者 self。
方法的定義格式如下:
其中,
舉個例子:
方法與函數(shù)的區(qū)別是,函數(shù)不屬于任何類型,方法屬于特定的類型。
指針類型的接收者
指針類型的接收者由一個結(jié)構(gòu)體的指針組成,由于指針的特性,調(diào)用方法時修改接收者指針的任意成員變量,在方法結(jié)束后,修改都是有效的。這種方式就十分接近于其他語言中面向?qū)ο笾械膖his或者self。 例如我們?yōu)镻erson添加一個SetAge方法,來修改實例變量的年齡。
調(diào)用該方法:
值類型的接收者
當(dāng)方法作用于值類型接收者時,Go語言會在代碼運行時將接收者的值復(fù)制一份。在值類型接收者的方法中可以獲取接收者的成員值,但修改操作只是針對副本,無法修改接收者變量本身。
什么時候應(yīng)該使用指針類型接收者
任意類型添加方法
在Go語言中,接收者的類型可以是任何類型,不僅僅是結(jié)構(gòu)體,任何類型都可以擁有方法。 舉個例子,我們基于內(nèi)置的int類型使用type關(guān)鍵字可以定義新的自定義類型,然后為我們的自定義類型添加方法。
注意事項: 非本地類型不能定義方法,也就是說我們不能給別的包的類型定義方法。
結(jié)構(gòu)體的匿名字段
匿名字段默認(rèn)采用類型名作為字段名,結(jié)構(gòu)體要求字段名稱必須唯一,因此一個結(jié)構(gòu)體中同種類型的匿名字段只能有一個。
嵌套結(jié)構(gòu)體
一個結(jié)構(gòu)體中可以嵌套包含另一個結(jié)構(gòu)體或結(jié)構(gòu)體指針。
嵌套匿名結(jié)構(gòu)體
當(dāng)訪問結(jié)構(gòu)體成員時會先在結(jié)構(gòu)體中查找該字段,找不到再去匿名結(jié)構(gòu)體中查找。
嵌套結(jié)構(gòu)體的字段名沖突
嵌套結(jié)構(gòu)體內(nèi)部可能存在相同的字段名。這個時候為了避免歧義需要指定具體的內(nèi)嵌結(jié)構(gòu)體的字段。
結(jié)構(gòu)體的“繼承”
Go語言中使用結(jié)構(gòu)體也可以實現(xiàn)其他編程語言中面向?qū)ο蟮睦^承。
結(jié)構(gòu)體字段的可見性
結(jié)構(gòu)體中字段大寫開頭表示可公開訪問,小寫表示私有(僅在定義當(dāng)前結(jié)構(gòu)體的包中可訪問)。
結(jié)構(gòu)體與JSON序列化
JSON(JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式。易于人閱讀和編寫。同時也易于機器解析和生成。JSON鍵值對是用來保存JS對象的一種方式,鍵/值對組合中的鍵名寫在前面并用雙引號""包裹,使用冒號:分隔,然后緊接著值;多個鍵值之間使用英文,分隔。
結(jié)構(gòu)體標(biāo)簽(Tag)
Tag是結(jié)構(gòu)體的元信息,可以在運行的時候通過反射的機制讀取出來。 Tag在結(jié)構(gòu)體字段的后方定義,由一對反引號包裹起來,具體的格式如下:
`key1:"value1" key2:"value2"`
結(jié)構(gòu)體標(biāo)簽由一個或多個鍵值對組成。鍵與值使用冒號分隔,值用雙引號括起來。鍵值對之間使用一個空格分隔。 注意事項: 為結(jié)構(gòu)體編寫Tag時,必須嚴(yán)格遵守鍵值對的規(guī)則。結(jié)構(gòu)體標(biāo)簽的解析代碼的容錯能力很差,一旦格式寫錯,編譯和運行時都不會提示任何錯誤,通過反射也無法正確取值。例如不要在key和value之間添加空格。
例如我們?yōu)镾tudent結(jié)構(gòu)體的每個字段定義json序列化時使用的Tag: