本篇內(nèi)容主要講解“Go語言怎么應(yīng)用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Go語言怎么應(yīng)用”吧!
創(chuàng)新互聯(lián)公司2013年開創(chuàng)至今,先為睢寧縣等服務(wù)建站,睢寧縣等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為睢寧縣企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。Go 的特征
我經(jīng)常說要學(xué)一樣?xùn)|西,首先要搞清楚它為什么會出現(xiàn)?解決了什么問題 ?
只要了解這些底層的根本問題,你才會有持續(xù)的動力深入學(xué)習(xí),而不是盲目跟風(fēng)和三分鐘熱度。
Go 語言是 google 在 2009年11月發(fā)布的項目,在編程語言里面算是非常年輕的小伙子。
至于 Go 語言的誕生和歷史,大家可以看看這篇文章:三分鐘了解 Go 語言的前世今生
我個人認(rèn)為 Go 的誕生是有時代的必要性,因為它主要解決主要是解決了:
動態(tài)語言的性能和弱類型問題
靜態(tài)語言的開發(fā)效率和復(fù)雜度,還有并發(fā)問題
我們都知道 Google 是世界上數(shù)據(jù)量較大的公司,Go 語言的輕量級線程設(shè)計,也幫助 Google 降低運(yùn)算和并發(fā)計算的成本,這也是 Go 語言能誕生的一個重要目的。
在數(shù)據(jù)爆炸的今天,Go 語言重新平衡了開發(fā)效率和運(yùn)行性能,所以 Go 會在未來十年,都是最重要的編程語言
關(guān)于 go 的定位,大家看下圖可能會更清晰:
剛接觸這門語言的時候,能感受到它的設(shè)計者是經(jīng)過認(rèn)真思考的,從不同語言遷移過來的開發(fā)者,可以從 Go 身上看到很多其他語言的影子,因為設(shè)計者借鑒了許多其他語言的設(shè)計,但是它也非常的克制,不是完全照搬,而且非常精準(zhǔn)的把優(yōu)秀并且使用的設(shè)計融入到 Go 當(dāng)中,將很多不實用且復(fù)雜的設(shè)計直接剔除。
雖然 Go 出自名門,你從 Go 身上看不到什么學(xué)院派的影子,沒有多余的設(shè)計,沒有復(fù)雜的概念,處處可見的 簡單,實用 的設(shè)計理念,因為它的創(chuàng)造者的理念是:
只有通過設(shè)計上的簡單性,系統(tǒng)才能在增長的過程中保持穩(wěn)定和自洽
Go 另外還有一個特點(diǎn)區(qū)別于其他語言的就是,Go 語言為了追求代碼可讀性,可能是第一個將代碼風(fēng)格在編譯器層面做出強(qiáng)制要求的語言。例如:
首字母大寫代表 public,代表導(dǎo)出類型,外部可訪問
首字母小寫代碼 private,代表非導(dǎo)出類型,僅內(nèi)部可訪問
還有對 {} 換行的限制,
編譯層面就不允許出現(xiàn)無用變量
等等&……
Go 對于動態(tài)語言:
寫過動態(tài)語言類似 Ruby,Python 的開發(fā)者,最頭痛的應(yīng)該就是類型問題,因為不確定類型,導(dǎo)致很多問題在編譯期無法被發(fā)現(xiàn),直接 runtime 的時候才能暴露出現(xiàn),處理成本極高。Go 語言提供簡單夠用的類型系統(tǒng),對于動態(tài)語言開發(fā)者不會有太大的手上成本,也幫助了動態(tài)語言的開發(fā)者解決大多數(shù)類型問題。
Go 對于靜態(tài)語言:
Go 語言并沒有去照搬 C++ 和 Java 那套超級復(fù)雜的類型系統(tǒng),Go 放棄了大量的 OOP 特性,不支持繼承和重載,對于 Java/C++ 等主流 OOP 編程語言,Go 可能也是一個徹頭徹尾的異類,但是不要懷疑 Go 也是一門面向?qū)ο蟮木幊陶Z言,只是他在用自己理解方法,一種不同尋常的方式來解釋面向?qū)ο?,它的特征如下?/p>
它沒有繼承、甚至沒有類
沒有繼承,通過組合來完成繼承
類型和接口都是非侵入式(無需聲明接口的實現(xiàn))
至于 Go 其他語言的區(qū)別,可以單獨(dú)列出一篇文章,這里暫時不深入討論了……
短賦值語句、遞增語句
符合 Java 程序員的習(xí)慣、Go 支持短賦值語句、遞增語句,下面簡單看一個示例即可:
x := 0 x += 5 fmt.Print(x) // x = 5 x++ fmt.Print(x) // x = 6 x-- fmt.Print(x) // x = 5
Go 雖然是靜態(tài)編譯型語言,但是擁有很多動態(tài)語言才有的語法特性,比如批量賦值、變量交換,示例:
// 批量賦值 x, y, z := 1, 2, 3 // 交換變量 x, y = y ,x
Java 程序員應(yīng)該很羨慕這種交換變量的寫法,因為在 Java 中想要交換變量必須要聲明一個很別扭的 tmp 臨時變量才能實現(xiàn)變量的交換
Go 只支持 for 一種循環(huán)語句(減少心智負(fù)擔(dān))
// for 格式 for init; condition; post{ // 循環(huán)邏輯 } for i := range ary { // for range 用于遍歷 slice 的快捷方法 }
Go 命名規(guī)范
不同于其他語言,Go 中的函數(shù)、變量、常量、類型和包都遵循一個簡單和統(tǒng)一的原則:
名稱開始是一個 Unicode 字符即可,區(qū)分大小寫
例如:HeapSort 和 heapSort 是不同的名稱
還有就是上面說到的,通過大小寫的命名規(guī)范,直接把 private 和 public 權(quán)限聲明的關(guān)鍵字這種并無很大作用的關(guān)鍵字給移除了,這種在不改變功能的前提下做減法,可謂是刀法快準(zhǔn)狠
另外在 Go 官方的 Demo 和文檔來看, Go 是比較推崇簡短的命名原則,有以下兩點(diǎn):
如果作用域越長,那么命名就應(yīng)該越清晰(也就是越長)
Go 是推崇駝峰命名法的,而不是 C 語言里面的下劃線分割法
關(guān)鍵字
我們先看一組數(shù)據(jù)對比:
C++ 關(guān)鍵字?jǐn)?shù)量 62 個
Java 關(guān)鍵字?jǐn)?shù)量 53 個
Go 關(guān)鍵字?jǐn)?shù)量 25 個
從關(guān)鍵字的數(shù)量上,也可以看得出 Go 語言的設(shè)計者的克制,對簡單設(shè)計哲學(xué)的踐行。也降低學(xué)習(xí)成本和學(xué)習(xí) Go 語言的心智負(fù)擔(dān),是一門對于初學(xué)者非常友好的語言
變量表達(dá)式
總結(jié)一下 Go 其實只有 4種可聲明的類型,主要如下:
變量:通過 var 或者 := 聲明
常量:通過關(guān)鍵字 const 聲明
類型:通過關(guān)鍵字 type 聲明
函數(shù):通過關(guān)鍵字 func 聲明
變量的標(biāo)準(zhǔn)聲明格式是:
var name type = expression // 上面聲明方式很清晰,但是很啰嗦,平時很少用,通常使用短變量的聲明格式 // 如下: name := expression // 短變量可以通過 expression 自動推導(dǎo) name 的類型
短變量聲明格式短小,靈活,所以是平時很常用的聲明方式。
另外在 Go 語言中,變量,常量都可以通過以下方式進(jìn)行批量聲明:
var ( ... ) const ( ... )
如果變量沒有初始化表達(dá)式,例如 var name int,那么會觸發(fā) Go 語言的零值機(jī)制(Default Value),具體每種類型對應(yīng)的零值,大家可以自行 Google,這里就不長篇大論了。
通過零值其實可以明白:Go 里面不存在沒有初始化的變量,這也保證了 Go 語言的健壯性,不容易出現(xiàn)低級錯誤
引用傳遞和值傳遞
熟悉 Go 語言基礎(chǔ)的都知道 Go 的引用傳遞在不加任何修飾符的情況下,默認(rèn)是值傳遞,為什么要這樣設(shè)計呢 ?
因為這樣的設(shè)計會為 Go 語言的垃圾回收帶來性能上的提升,值傳遞可以較大化的減少變量的逃逸行為,變量會較大概率的被分配到棧上,棧上分配的變量是無需等待 GC 的回收,還可以減少堆內(nèi)存的占用和 GC 的壓力,倒不是要大家去學(xué)習(xí)垃圾回收的工作原理,或者特別去關(guān)心變量的逃逸行為,但是對于變量的生命周期還是要搞清楚的。
在 Go 里面通過表達(dá)式的 &variable 可以獲取該變量的指針,通過 *pointer 可以獲取該指針變量的值,這是眾所周知的事情,所以在 Go 里面想要傳遞引用也是很簡單的事情,并且使用指針可以在無需知道變量名字的情況下,讀取和更新變量。
指針是可以比較的,相同值的指針必然相同,我們看一段代碼:
p := 0 // 聲明類型 &p != nil // true, 比較指針,說明 p 當(dāng)前指向一個變量 var x, y int // 聲明類型, default value 0 &x == &x // true, 相同指針結(jié)果必然相等 &x == &y // false,指針不同,結(jié)果不相等
函數(shù)參數(shù)也可以通過 * 表示當(dāng)前參數(shù)的傳遞類型,例如函數(shù):func incr(p *int) 表示當(dāng)前 p 參數(shù)是指針傳遞,不過多年編程經(jīng)驗來看,這樣引用傳遞過多的話,可能你的程序庫龐大后,或者你想找到一個被經(jīng)常傳遞的引用變量在哪里被修改的,你可能會很難找到和定位,這可能是傳遞指針?biāo)鶐淼囊粋€副作用吧
基本類型
Go 的基本類型也很少,常用的也就是:整型(int)、浮點(diǎn)(flora)、布爾(bool)、字符串(string)、復(fù)數(shù)(complex),和 Java 的不同之處在于,string 在 Go 里面是內(nèi)置的基本數(shù)據(jù)類型,在 Java 中確實一個實體類。不過我個人感受 String 本就應(yīng)該是基本數(shù)據(jù)類型。用類組合 byte[] 來實現(xiàn)字符串似乎還是有些別扭。
整數(shù)
這里主要區(qū)分有符號整數(shù)、無符號整數(shù)。
不過無符號因為無法表達(dá)負(fù)數(shù),所以平時使用場景比較少,往往只用于數(shù)據(jù)庫自增 ID,位運(yùn)算和特定算數(shù),實現(xiàn)位集,解析二進(jìn)制等,這里要了解平時還是使用 int 等有符號整數(shù)比較多就好,具體區(qū)分如下:
有符號整數(shù):int8、int16、int32、int64
無符號整數(shù):uint8、uint16、uint32、uint64
Int 后面的數(shù)字代表類型的大小,也就是 2N 次冪,使用明確的類型可以更好的利用內(nèi)存空間,Go 語言的所有二元操作符和其他語言別無二致,另外 Go 不支持三元表達(dá)式,原因我也不知道為什么,個人猜測可能是因為考慮函數(shù)多返回值的原因,但是 if/else 這樣的代碼就要寫很多了,感覺還是挺嘔心的。
浮點(diǎn)數(shù) float32、float64 也沒什么好講的,都很簡單,只有一個原則,如果想要減少浮點(diǎn)運(yùn)算誤差,盡量推薦使用 float64,因為 float64 有效數(shù)是 15 位,差不多是 float32 的 3倍
復(fù)數(shù)(complex)目前看上去很少用,后面用到再聊聊……
布爾類型(bool)除了名字短點(diǎn),基本和其他語言沒有區(qū)別,跳過
字符串
可以簡單聊聊,string 是 Go 的基本數(shù)據(jù)類型,這點(diǎn)和 Java 的類型有些不同,但是相同點(diǎn)還是蠻多的,例如:
都可以通過加號(+)拼接字符串,但是返回新的字符串(但性能敏感慎用)
不知道是不是 Go 語言設(shè)計者同時也是 UTF-8 編碼的設(shè)計者(Rob、Ken),所以 Go 語言源文件默認(rèn)就是 UTF8 編碼,可以預(yù)見到使用 Go 語言會大大減少亂碼問題。
另外介紹幾個 Go 常用處理字符的工具包,如下:
strings:提供搜索、比較、替換等平時常用的字符操作函數(shù)
bytes:顧名思義,提供操作 byte[] 類型的函數(shù)
strconv:提供布爾,整數(shù),浮點(diǎn)等其他類型轉(zhuǎn)為 string 的服務(wù)
unicode:提供對于文字符號特性判斷的函數(shù)服務(wù)
命名返回值
Go 語言可以在返回類型中,給返回值命名,所以在 return 中就無需再顯示返回,代碼如下
func split(sum int) (x, y int) { x = sum + 3 y = sum + x return // 將變量直接返回 } func main() { fmt.Println(split(50)) // res:53, 103 }
不過這種靈活的寫法,會對影響代碼的可讀性,不利于團(tuán)隊協(xié)作。不推薦使用。
從代碼可讀性和團(tuán)隊協(xié)作的角度來說,建議寫成如下方式,代碼更可讀,如下:
func split(sum int) (int, int) { x := sum + 3 y := sum + x return x, y } func main() { fmt.Println(split(50)) // res:53, 103 }
常量
值得注意的是,常量使用 const 關(guān)鍵字,任何基本數(shù)據(jù)類型都可以聲明為常量,但是不能使用 := 語法聲明,示例:
const Pi = 3.14 const World = "世界" const Truth = true
跟 import 類似可以批量聲明,這樣可以減少很多 const 重復(fù)聲明,,如下:
const ( Pi = 3.14 World = "世界" Truth = true )
循環(huán)
只有 for 一種循環(huán),簡單用法如下:
sum := 0 for i := 0; i < 10; i++ { sum += i }
Go語言的循環(huán)和 Java、Javascript 的區(qū)別主要在于沒有小括號,但是大括號則是必須的
很多編程語言都有 while 語句,但是在 Go 里面也是可以用 for 替代,如下:
sum := 1 for sum < 100 { sum += 1 // sum 累積 100 次 } // out: 100
if
跟 for 類似,if 也是沒有小括號的,其他方面和常見的語言差不多,如下:
if x < 0 { fmt.Println('x < 0') }
比較有特色的是,Go語言的 if 可以在執(zhí)行表達(dá)式之前,執(zhí)行一段聲明語句,如下:
func conditon(x, n, lim float64) float64 { // 初始化 v 變量,在進(jìn)行表達(dá)式判定 // 值得注意的是:v 是 if 條件內(nèi)的局部變量,外部無法調(diào)用 if v := x * n; v < lim { return v } return lim } condition(3, 5, 10) // out: 10
switch
switch 是簡化一連串 if else 的利器,不過 Go 語言的 switch 和其他語言差別不大,這里就不多說了。。
延遲函數(shù) defer
算是 Go 語言的特色,Go 的語言運(yùn)行機(jī)制保證它會在函數(shù)返回后執(zhí)行,所以通常用于關(guān)閉資源(網(wǎng)絡(luò)/文件/IO)等操作,如下:
defer fmt.Println("end") // 最先聲明,但會在最后執(zhí)行 fmt.Println("hello") fmt.Println("Phoenix") //out: //hello //Phoenix //end
值得注意的是,在使用 defer 聲明函數(shù)被壓力棧中,所以有多個 defer 聲明會根據(jù) FIFO 先進(jìn)先出的順序執(zhí)行,如下
defer fmt.Println("1") defer fmt.Println("2") defer fmt.Println("3") fmt.Println("done") // done // 3 // 2 // 1
指針
Go 通過 & 可以直接操作指針,并且通過 * 操作符可以通過指針修改引用值,如下:
x, y = 100, 200 p := &x // get i 指針 *p = 21 // 通過指針修改引用值 fmt.Println(x) //out x = 21
slice 切片
是 Go 語言比較常用的動態(tài)數(shù)組,值得注意的是它的傳遞是引用的,任何對切出來的變量進(jìn)行修改,都會影響到原本的值,代碼如下:
names := []string{ "金剛", "哥斯拉", "怪獸", "奧特曼" } a := names[0:2] // out:[金剛,哥斯拉] b := names[1:3] // out:[哥斯拉,怪獸] b[0] = "XXX" fmt.Println(a) // out:[金剛,XXX] fmt.Println(b) // out:[XXX,怪獸] fmt.Println(names)// out:[金剛,XXX,怪獸,奧特曼]
備注:聲明一個 slice 就像聲明一個沒有長度的數(shù)組
slice 的快捷切片寫法:
s := []int{2, 3, 5, 7, 11, 13} s = s[1:4] // out: 3, 5, 7 // s[0:2] 的簡寫 s = s[:2] // out: 3, 5 s = s[1:] // out: 5
在 slice 中 length 和 capacity 是分開存儲,例如上面改變長度,并不會改變?nèi)萘?,?slice 中的長度和容量可以通過函數(shù) len() 和 cap() 獲取,參考以下幾行代碼:
s := []int{2, 3, 5, 7, 11, 13} // len=6, cap=6 s = s[:0] // len=0, cap=6 s = s[:4] // len=4, cap=6
Map
Go 語言 map 的簡單用法:
// 使用字面量,聲明并且初始化一個簡單的 map,[key:string,value:int] s := map[string]int{"a": 123, "b": 456, "c":789} // out: map[a:123 b:456 c:789] // 插入和更新 s["d"] = 1001 // out: map[a:123 b:456 c:789, d:1001] //刪除元素 delete(s, "d") // out: map[a:123 b:456 c:789] // 檢索元素 value = s["a"] // out: 123 // 比較常用的快捷檢索 if v, ok := s["a"]; ok { fmt.Println("the value is >", v) // out: 123 }
函數(shù)變量
在 Go 中函數(shù)可以作為變量復(fù)制,也可以作為參數(shù)被引用
// 聲明函數(shù)參數(shù)為函數(shù)變量,fn 則執(zhí)行該函數(shù) func compute(fn func(float64, float64) float64) float64 { return fn(3, 4) } // 聲明函數(shù)變量 hypot := func(x, y float64) float64 { return math.Sqrt(x*x + y*y) } // 傳遞函數(shù)變量 hypot(5, 12) // out: 13 compute(hypot) // out: 5
閉包
Go 的閉包是一段匿名函數(shù),并且可以訪問外部的局部變量,如下 adder 返回一個函數(shù)閉包:
func adder() func(int) int { sum := 5 return func(x int) int { sum += x return sum } } // 聲明 pos 函數(shù)變量 pos := adder() fmt.Println(pos(5)) // out: 10
到此,相信大家對“Go語言怎么應(yīng)用”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)建站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
當(dāng)前標(biāo)題:Go語言怎么應(yīng)用-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://jinyejixie.com/article18/hgggp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站維護(hù)、建站公司、網(wǎng)站建設(shè)、微信小程序
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容