本文介紹一些Go語(yǔ)言的基礎(chǔ)語(yǔ)法。
創(chuàng)新互聯(lián)專(zhuān)注為客戶(hù)提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、豐臺(tái)網(wǎng)絡(luò)推廣、微信小程序、豐臺(tái)網(wǎng)絡(luò)營(yíng)銷(xiāo)、豐臺(tái)企業(yè)策劃、豐臺(tái)品牌公關(guān)、搜索引擎seo、人物專(zhuān)訪(fǎng)、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供豐臺(tái)建站搭建服務(wù),24小時(shí)服務(wù)熱線(xiàn):13518219792,官方網(wǎng)址:www.cdcxhl.com
先來(lái)看一個(gè)簡(jiǎn)單的go語(yǔ)言代碼:
go語(yǔ)言的注釋方法:
代碼執(zhí)行結(jié)果:
下面來(lái)進(jìn)一步介紹go的基礎(chǔ)語(yǔ)法。
go語(yǔ)言中格式化輸出可以使用 fmt 和 log 這兩個(gè)標(biāo)準(zhǔn)庫(kù),
常用方法:
示例代碼:
執(zhí)行結(jié)果:
更多格式化方法可以訪(fǎng)問(wèn)中的fmt包。
log包實(shí)現(xiàn)了簡(jiǎn)單的日志服務(wù),也提供了一些格式化輸出的方法。
執(zhí)行結(jié)果:
下面來(lái)介紹一下go的數(shù)據(jù)類(lèi)型
下表列出了go語(yǔ)言的數(shù)據(jù)類(lèi)型:
int、float、bool、string、數(shù)組和struct屬于值類(lèi)型,這些類(lèi)型的變量直接指向存在內(nèi)存中的值;slice、map、chan、pointer等是引用類(lèi)型,存儲(chǔ)的是一個(gè)地址,這個(gè)地址存儲(chǔ)最終的值。
常量是在程序編譯時(shí)就確定下來(lái)的值,程序運(yùn)行時(shí)無(wú)法改變。
執(zhí)行結(jié)果:
執(zhí)行結(jié)果:
Go 語(yǔ)言的運(yùn)算符主要包括算術(shù)運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、位運(yùn)算符、賦值運(yùn)算符以及指針相關(guān)運(yùn)算符。
算術(shù)運(yùn)算符:
關(guān)系運(yùn)算符:
邏輯運(yùn)算符:
位運(yùn)算符:
賦值運(yùn)算符:
指針相關(guān)運(yùn)算符:
下面介紹一下go語(yǔ)言中的if語(yǔ)句和switch語(yǔ)句。另外還有一種控制語(yǔ)句叫select語(yǔ)句,通常與通道聯(lián)用,這里不做介紹。
if語(yǔ)法格式如下:
if ... else :
else if:
示例代碼:
語(yǔ)法格式:
另外,添加 fallthrough 會(huì)強(qiáng)制執(zhí)行后面的 case 語(yǔ)句,不管下一條case語(yǔ)句是否為true。
示例代碼:
執(zhí)行結(jié)果:
下面介紹幾種循環(huán)語(yǔ)句:
執(zhí)行結(jié)果:
執(zhí)行結(jié)果:
也可以通過(guò)標(biāo)記退出循環(huán):
--THE END--
C89/C90標(biāo)準(zhǔn):定義數(shù)組時(shí)下標(biāo)只允許使用整型、字符型常量。引用數(shù)組時(shí)下標(biāo)可以使用整型、字符型的常量或者變量。C99標(biāo)準(zhǔn):定義數(shù)組時(shí)下標(biāo)可以使用整型、字符型的常量或變量,但變量必須已經(jīng)賦值。引用數(shù)組時(shí)下標(biāo)可以使用整型、字符型的常量或者
package main
import "fmt"
var arr [2]int //申明一個(gè)數(shù)組
func main() {
arr[0] = 1 //數(shù)組賦值
fmt.Println(arr)
arrtest := [3]int{1, 2, 3} //數(shù)組的另一種申明方式
fmt.Println(arrtest)
a := [...]int{1, 2} //[...]自動(dòng)識(shí)別數(shù)組的長(zhǎng)度
fmt.Println(a)
fmt.Println(len(a))//輸出數(shù)組的長(zhǎng)度
}
下邊是slice的申明和使用其實(shí)這就是一種動(dòng)態(tài)的數(shù)組
復(fù)制代碼 代碼如下:
package main
import "fmt"
func main() {
d := []int{1, 2, 3} //申明一個(gè)slice這個(gè)是動(dòng)態(tài)的數(shù)組,沒(méi)有長(zhǎng)度
fmt.Println(d)
var q, w []int
q = d[0:1] //可以定取得上邊的長(zhǎng)度
w = d[1:3]
d = append(d, 2) //向其中添加元素
fmt.Println(d)
fmt.Println(q, w)
}
操作字符串離不開(kāi)字符串的拼接,但是Go中string是只讀類(lèi)型,大量字符串的拼接會(huì)造成性能問(wèn)題。
拼接字符串,無(wú)外乎四種方式,采用“+”,“fmt.Sprintf()”,"bytes.Buffer","strings.Builder"
上面我們創(chuàng)建10萬(wàn)字符串拼接的測(cè)試,可以發(fā)現(xiàn)"bytes.Buffer","strings.Builder"的性能最好,約是“+”的1000倍級(jí)別。
這是由于string是不可修改的,所以在使用“+”進(jìn)行拼接字符串,每次都會(huì)產(chǎn)生申請(qǐng)空間,拼接,復(fù)制等操作,數(shù)據(jù)量大的情況下非常消耗資源和性能。而采用Buffer等方式,都是預(yù)先計(jì)算拼接字符串?dāng)?shù)組的總長(zhǎng)度(如果可以知道長(zhǎng)度),申請(qǐng)空間,底層是slice數(shù)組,可以以append的形式向后進(jìn)行追加。最后在轉(zhuǎn)換為字符串。這申請(qǐng)了不斷申請(qǐng)空間的操作,也減少了空間的使用和拷貝的次數(shù),自然性能也高不少。
bytes.buffer是一個(gè)緩沖byte類(lèi)型的緩沖器存放著都是byte
是一個(gè)變長(zhǎng)的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一個(gè) 空的 buffer,但是可以使用,底層就是一個(gè) []byte, 字節(jié)切片。
向Buffer中寫(xiě)數(shù)據(jù),可以看出Buffer中有個(gè)Grow函數(shù)用于對(duì)切片進(jìn)行擴(kuò)容。
從Buffer中讀取數(shù)據(jù)
strings.Builder的方法和bytes.Buffer的方法的命名幾乎一致。
但實(shí)現(xiàn)并不一致,Builder的Write方法直接將字符拼接slice數(shù)組后。
其沒(méi)有提供read方法,但提供了strings.Reader方式
Reader 結(jié)構(gòu):
Buffer:
Builder:
可以看出Buffer和Builder底層都是采用[]byte數(shù)組進(jìn)行裝載數(shù)據(jù)。
先來(lái)說(shuō)說(shuō)Buffer:
創(chuàng)建好Buffer是一個(gè)empty的,off 用于指向讀寫(xiě)的尾部。
在寫(xiě)的時(shí)候,先判斷當(dāng)前寫(xiě)入字符串長(zhǎng)度是否大于Buffer的容量,如果大于就調(diào)用grow進(jìn)行擴(kuò)容,擴(kuò)容申請(qǐng)的長(zhǎng)度為當(dāng)前寫(xiě)入字符串的長(zhǎng)度。如果當(dāng)前寫(xiě)入字符串長(zhǎng)度小于最小字節(jié)長(zhǎng)度64,直接創(chuàng)建64長(zhǎng)度的[]byte數(shù)組。如果申請(qǐng)的長(zhǎng)度小于二分之一總?cè)萘繙p去當(dāng)前字符總長(zhǎng)度,說(shuō)明存在很大一部分被使用但已讀,可以將未讀的數(shù)據(jù)滑動(dòng)到數(shù)組頭。如果容量不足,擴(kuò)展2*c + n 。
其String()方法就是將字節(jié)數(shù)組強(qiáng)轉(zhuǎn)為string
Builder是如何實(shí)現(xiàn)的。
Builder采用append的方式向字節(jié)數(shù)組后添加字符串。
從上面可以看出,[]byte的內(nèi)存大小也是以倍數(shù)進(jìn)行申請(qǐng)的,初始大小為 0,第一次為大于當(dāng)前申請(qǐng)的最大 2 的指數(shù),不夠進(jìn)行翻倍.
可以看出如果舊容量小于1024進(jìn)行翻倍,否則擴(kuò)展四分之一。(2048 byte 后,申請(qǐng)策略的調(diào)整)。
其次String()方法與Buffer的string方法也有明顯區(qū)別。Buffer的string是一種強(qiáng)轉(zhuǎn),我們知道在強(qiáng)轉(zhuǎn)的時(shí)候是需要進(jìn)行申請(qǐng)空間,并拷貝的。而B(niǎo)uilder只是指針的轉(zhuǎn)換。
這里我們解析一下 *(*string)(unsafe.Pointer(b.buf)) 這個(gè)語(yǔ)句的意思。
先來(lái)了解下unsafe.Pointer 的用法。
也就是說(shuō),unsafe.Pointer 可以轉(zhuǎn)換為任意類(lèi)型,那么意味著,通過(guò)unsafe.Pointer媒介,程序繞過(guò)類(lèi)型系統(tǒng),進(jìn)行地址轉(zhuǎn)換而不是拷貝。
即*A = Pointer = *B
就像上面例子一樣,將字節(jié)數(shù)組轉(zhuǎn)為unsafe.Pointer類(lèi)型,再轉(zhuǎn)為string類(lèi)型,s和b中內(nèi)容一樣,修改b,s也變了,說(shuō)明b和s是同一個(gè)地址。但是對(duì)s重新賦值后,意味著s的地址指向了“WORLD”,它們所使用的內(nèi)存空間不同了,所以s改變后,b并不會(huì)改變。
所以他們的區(qū)別就在于 bytes.Buffer 是重新申請(qǐng)了一塊空間,存放生成的string變量, 而strings.Builder直接將底層的[]byte轉(zhuǎn)換成了string類(lèi)型返回了回來(lái),去掉了申請(qǐng)空間的操作。
下邊是slice的申明和使用其實(shí)這就是一種動(dòng)態(tài)的數(shù)組復(fù)制代碼 代碼如下:package main
import "fmt"func main() {d := []int{1, 2, 3} //申明一個(gè)slice這個(gè)是動(dòng)態(tài)的數(shù)組,沒(méi)有長(zhǎng)fmt.Println(d)
var q, w []intq = d[0:1] //可以定取得上邊的長(zhǎng)度w = d[1:3]d = append(d, 2) //向其中添加元素fmt.Println(d)fmt.Printlnw。
Go語(yǔ)言是谷歌2009年發(fā)布的第二款開(kāi)源編程語(yǔ)言。Go語(yǔ)言專(zhuān)門(mén)針對(duì)多處理器系統(tǒng)應(yīng)用程序的編程進(jìn)行了優(yōu)化,使用Go編譯的程序可以媲美C或C++代碼的速度,而且更加安全、支持并行進(jìn)程。北京時(shí)間2010年1月10日,Go語(yǔ)言摘得了TIOBE公布的2009年年度大獎(jiǎng)。
在谷歌公開(kāi)發(fā)布的所有網(wǎng)絡(luò)應(yīng)用中,均沒(méi)有使用Go,但是谷歌已經(jīng)使用該語(yǔ)言開(kāi)發(fā)了幾個(gè)內(nèi)部項(xiàng)目。派克表示,Go是否會(huì)對(duì)谷歌即將推出的Chrome OS產(chǎn)生影響,還言之尚早,不過(guò)Go的確可以和Native Client配合使用。他表示“Go可以讓?xiě)?yīng)用完美的運(yùn)行在瀏覽器內(nèi)?!崩纾褂肎o可以更高效的實(shí)現(xiàn)Wave,無(wú)論是在前端還是后臺(tái)。
Go 同時(shí)具有兩種編譯器,一種是建立在GCC基礎(chǔ)上的Gccgo,另外一種是分別針對(duì)64位x64和32位x86計(jì)算機(jī)的一套編譯器(6g和8g)。谷歌目前正在研發(fā)其對(duì)ARM芯片和Android設(shè)備的支持。
Google對(duì)Go寄予厚望。其設(shè)計(jì)是讓軟件充分發(fā)揮多核心處理器同步多工的優(yōu)點(diǎn),并可解決面向?qū)ο蟪绦蛟O(shè)計(jì)的麻煩。它具有現(xiàn)代的程序語(yǔ)言特色,如垃圾回收,幫助程序設(shè)計(jì)師處理瑣碎但重要的內(nèi)存管理問(wèn)題。Go的速度也非???,幾乎和C或C++程序一樣快,且能夠快速制作程序。