寫了快一個月的Go,已經沒有什麼陌生感了。bash
一行代碼寫完,不會在行尾本能的敲上「;」,直接Enter鍵換行;架構
定義變量把變量名放在前面,類型放在後面;框架
使用struct去定義本身想要的數據模型就比如定義一個Java中的model同樣……函數
這些不用能夠通過大腦加工思考,就想本身還在寫Java同樣。微服務
還記得當時在看《Go實戰》的時候看到變量類型後置的聲明方式,我還在極力吐槽這種不人性的語法,若是我已經站在了真香的隊伍裏,和其餘的真香同窗別無二致。工具
感慨,人的適應能力真的強👍ui
做爲一個Java重度愛好者,其實在每次寫Go的時候都會不由自主的把二者進行對比,在寫文章的時候也會常常提到。固然了,今天主要說的仍是Go的函數。spa
func f(a int, b int) (ret int, err error) {
fmt.Println("This is function")
return
}
複製代碼
沒錯,這大概就是一個典型的Go風格的函數,那麼它有哪些特點code
入參的變量也是變量後置的,這裏a變量和b變量是相同類型的,因此也能夠寫成cdn
a, b int
複製代碼
對於不一樣類型的參數須要分開定義。
除此之外,入參還支持不定參數
好比能夠這樣定義
func f(args ...int) {
for _, arg := range args {
fmt.Println(arg)
}
}
複製代碼
針對不定參數的函數,咱們能夠這樣調用
f(1)
f(1, 2)
f(1, 2, 3)
避免了咱們在函數裏定義一長串變量的狀況。
上面的不定參數是int類型的,那麼是否支持多種類型混用的不定參數呢?
是能夠的,使用...interface{}這種形式
func f(args ...interface{}) {
for _, arg := range args {
switch arg.(type) {
case int:
fmt.Println("It is int type")
case string:
fmt.Println("It is string type")
case int64:
fmt.Println("It is int64 type")
}
}
}
複製代碼
注意,這裏的i.(T)形式不是強制轉換或者隱式類型轉換,這是類型斷言,表示斷定類型的。
Go裏面是沒有隱式類型轉換的,不只沒有,並且強制類型轉換也很嚴格。
不一樣於Java,Go函數是能夠支持多返回值的,好比這裏返回了ret和err兩個參數。
返回值的定義方式也很靈活,能夠寫成
func f(a int, b int) (int, error) {
fmt.Println("This is function")
return
}
複製代碼
若是返回只有一個參數能夠寫成
func f(a int, b int) (ret int) {
fmt.Println("This is function")
return
}
複製代碼
或者
func f(a int, b int) int {
fmt.Println("This is function")
return
}
複製代碼
在前面的文章,咱們也順帶提過,對於函數返回的值,有些咱們不關心或者不須要的話,咱們不能抹掉他的位置,可是可使用"_"來表示這個參數的存在,只是不用而已,好比這樣調用上面的函數是不行的
ret := f(1, 2) // 缺乏err返回值
複製代碼
可是這樣是OK的
ret, _ := f(1, 2)
複製代碼
或者這樣
_, err := f(1, 2)
複製代碼
error接口是Go標準庫爲了錯誤處理提供的接口。
通常在業務代碼中,咱們會調用某個方法後,斷定方法對應的值是否爲nil斷定方法是否被正常執行
if err != nil {
// 沒有正常執行
} else {
// 正常執行
}
複製代碼
說到error,正好說說panic()和recover()兩個函數
當咱們遇到一些err的時候,咱們可能就會直接拋出panic,這裏的panic能夠近似理解爲Java裏面的Exception,即拋出異常。
if err != nil {
panic(err)
}
複製代碼
一旦拋出panic,則程序將會終止,除非遇到一種狀況,即有recover的存在。
說到recover則不得不提defer
defer是Go裏面的新特性,有點類型Java裏面的finally,承擔回收資源或者解鎖這類的收尾工做,可是比finally要靈活,Go函數的defer能夠放在函數的任意位置,無論函數是否正常執行,在跳出函數前都會執行defer定義的函數。
接着說recover,若是在函數拋出panic,只要在最後遇到recover也是能夠恢復正常的,形式以下
defer func() {
if ret := recover(); ret != nil {
fmt.Println("Catch Runtime Error:)
}
}
複製代碼
每一個函數都以func開始,來代表本身是一個函數。
那麼學過Java的確定會問,沒有像public、private這樣的訪問修飾符嗎?
沒有,可是Go經過另一種規則實現了訪問範圍便可見性。對於函數名使用大寫字母開頭,則表示能夠被其餘包使用,若是使用小寫字母開頭,則只能本包內使用。
固然,這個規則,也適用於變量的聲明。
和Java等其餘語言同樣,Go函數也有匿名函數。
func (a, b int, s string) int {
...
}
複製代碼
能夠經過直接在後面賦值的方式直接執行
func (a, b int, s string) int {
...
}(1, 2, "test")
複製代碼
這裏主要從Go語言的函數構成包括關鍵字func,入參和返回值介紹Go函數的一些特性。固然了,Go函數還有不少靈活性就再也不一一闡述了,有待你我在業務項目中慢慢實踐體會了。
今天去參加了一個技術沙龍,主題是數據存儲與微服務架構實踐方面的。
這是本身第一次除了參加公司組織的各類會議之外,本身主動報名的線下技術沙龍。
會上聽到了阿里、百度的大佬分享關於過去的技術沉澱和對將來技術方向的展望,總體仍是蠻有收穫的。
拓寬了本身的知識面,也加深了對一些框架或者工具的理解,好比ServiceMesh。以前對於ServiceMesh的理解僅限於閱讀各類文章,本身的理解也比較有限,此次經過阿里大佬的解釋,更加清晰的瞭解了ServiceMesh以及它的優點。
最後曬一下在回答問題環節,主辦方送的馬克杯,好評
我的公衆號:JackieZheng 我會將我最新的文章推送給您,並和您一塊兒分享我平常閱讀過的優質文章