Go語(yǔ)言函數(shù)、包
Go語(yǔ)言函數(shù)、包
函數(shù)使用:
①函數(shù)的形參列表可以是多個(gè),返回值列表也可以是多個(gè)。
②形參列表和返回值列表的數(shù)據(jù)類型可以是值類型和引用類型。
③函數(shù)的命名遵循標(biāo)識(shí)符命名規(guī)范,首字母不能是數(shù)字,首字母大寫該函數(shù)可以被本包文件和其它包文件使用,類似 public,首字母小寫,只能被本包文件使用,其它包文件不能使用,類似 private。
④函數(shù)中的變量是局部的,函數(shù)外不生效。
⑤基本數(shù)據(jù)類型和數(shù)組默認(rèn)都是值傳遞的,即進(jìn)行值拷貝。在函數(shù)內(nèi)修改,不會(huì)影響到原來的值。
⑥如果希望函數(shù)內(nèi)的變量能修改函數(shù)外的變量(指的是默認(rèn)以值傳遞的方式的數(shù)據(jù)類型),可以傳入變量的地址&,函數(shù)內(nèi)以指針的方式操作變量。Test(&num)
⑦Go語(yǔ)言不支持函數(shù)重載
⑧在Go中,函數(shù)也是一種數(shù)據(jù)類型,可以賦值給一個(gè)變量,則該變量就是一個(gè)函數(shù)類型的變量了。通過該變量可以對(duì)函數(shù)調(diào)用。

⑨函數(shù)可作為形參,并且調(diào)用。

⑩Go支持自定義數(shù)據(jù)類型:基本語(yǔ)法:type自定義數(shù)據(jù)類型名數(shù)據(jù)類型
案例:type mySum??func (int, int) int
這時(shí)mxSum就等價(jià)一個(gè)函數(shù)類型func(int, int)int
①支持對(duì)函數(shù)返回值命名
?

②使用_標(biāo)識(shí)符,忽略返回值。
③支持可變參數(shù)。
?
args是slice切片,通過args[index]可以訪問到各個(gè)值。
如果一個(gè)函數(shù)的形參列表中有可變參數(shù),則可變參數(shù)需要放在形參列表最后。
?
Init函數(shù)
每一個(gè)源文件都可以包含一個(gè)init函數(shù),其會(huì)在main函數(shù)執(zhí)行前,被Go運(yùn)行框架調(diào)用。
①如果一個(gè)文件同時(shí)包含全局變量定義,init函數(shù)和main函數(shù),則執(zhí)行的流程:
全局變量定義?→ init函數(shù)?→main函數(shù)
②主要完成初始化操作。
③案例如果main.go和utils.go都含有變量定義,init函數(shù)時(shí),執(zhí)行的流程:
?

?
匿名函數(shù)
使用方法:
①在定義匿名函數(shù)時(shí)就直接調(diào)用【只能調(diào)用一次】
?

②將匿名函數(shù)賦給一個(gè)變量(函數(shù)變量),再通過該變量來調(diào)用匿名函數(shù)
?

?全局匿名函數(shù):將匿名函數(shù)賦給一個(gè)全局變量
?

閉包:一個(gè)函數(shù)和與其相關(guān)的引用環(huán)境組合的一個(gè)整體(實(shí)體)。
請(qǐng)編寫一個(gè)程序,具體要求如下
①編寫一個(gè)函數(shù)makeSuffix(suffix string)可接收一個(gè)文件后綴名(如.jpg),并返回一個(gè)閉包。
②調(diào)用閉包,可以傳入一個(gè)文件名,如果該文件名無指定的后綴(如.ipg) ,則返回文件名.jpg;若有.jpg后綴,則返回原文件名。
③要求使用閉包的方式完成
④strings.HasSuffix,該函數(shù)可以判斷某個(gè)字符串是否有指定的后綴。
?

返回的匿名函數(shù)和makesSuffix (suffix string)的suffix變量組合成一個(gè)閉包,因?yàn)榉祷氐暮瘮?shù)引用到suffix這個(gè)變量。
傳統(tǒng)方法需要每次都傳入后綴名,而閉包因?yàn)榭梢员A羯洗我玫哪硞€(gè)值,所以我們傳入一次就可以反復(fù)使用。
?
函數(shù)的defer(延時(shí)機(jī)制)
在函數(shù)中,程序員經(jīng)常需要?jiǎng)?chuàng)建資源(如:數(shù)據(jù)庫(kù)連接、文件句柄、鎖等),為了在函數(shù)執(zhí)行完畢后,及時(shí)的釋放資源,Go的設(shè)計(jì)者提供 defer。

①當(dāng)go執(zhí)行到一個(gè)defer時(shí),不會(huì)立即執(zhí)行defer后的語(yǔ)句,而是將defer后的語(yǔ)句壓入到一個(gè)棧中,然后繼續(xù)執(zhí)行函數(shù)下一個(gè)語(yǔ)句。
②當(dāng)函數(shù)執(zhí)行完畢后,再?gòu)膁efer棧中,依次從棧頂取出語(yǔ)句執(zhí)行。
③在defer將語(yǔ)句放入到棧時(shí),也會(huì)將相關(guān)的值拷貝同時(shí)入棧。
?

defer最主要的價(jià)值是在,當(dāng)函數(shù)執(zhí)行完畢后,可以及時(shí)的釋放函數(shù)創(chuàng)建的資源。
①在golang編程中的通常做法是,創(chuàng)建資源后,比如(打開了文件,獲取了數(shù)據(jù)庫(kù)的鏈接,或者是鎖資源),可以執(zhí)行defer file.Close() ;defer connect.Close()
②在 defer后,可以繼續(xù)使用創(chuàng)建資源。
③當(dāng)函數(shù)完畢后,系統(tǒng)會(huì)依次從defer棧中,取出語(yǔ)句,關(guān)閉資源。
④這種機(jī)制,非常簡(jiǎn)潔,程序員不用再為在什么時(shí)機(jī)關(guān)閉資源而煩心。
?
函數(shù)傳遞:
不管是值傳遞還是引用傳遞,傳遞給函數(shù)的都是變量的副本,不同的是,值傳遞的是值的拷貝,引用傳遞的是地址的拷貝。
值類型:基本數(shù)據(jù)類型int 系列,?float系列,bool,string、數(shù)組和結(jié)構(gòu)體struct
引用類型:指針、slice 切片、map、管道chan、interface等都是引用類型
?
變量作用域:
①函數(shù)內(nèi)部聲明/定義的變量叫局部變量,作用域僅限于函數(shù)內(nèi)部
②函數(shù)外部聲明/定義的變量叫全局變量,作用域在整個(gè)包都有效,如果其首字母為大寫,則作用域在整個(gè)程序有效。
③如果變量是在一個(gè)代碼塊,這個(gè)變量的的作用域就在該代碼塊。
?

字符串常用的系統(tǒng)函數(shù):
①統(tǒng)計(jì)字符串的長(zhǎng)度,按字節(jié)len(str)
②字符串遍歷,同時(shí)處理有中文的問題r :=[]rune(str)
③字符串轉(zhuǎn)整數(shù): n, err := strconv.Atoi("12")
④整數(shù)轉(zhuǎn)字符串:str =strconx.Itoa(12345)
⑤字符串轉(zhuǎn)[]byte: var bytes =[]byte("hello go")
⑥[]byte轉(zhuǎn)字符串: str = string([]byte {97,98,99})
⑦10進(jìn)制轉(zhuǎn)2,8,16進(jìn)制: str = strconv.FormatInt(123,2)//2→8,16
⑧查找子串是否在指定的字符串中: strings.Contains("seafood", "foo")//true
⑨統(tǒng)計(jì)一個(gè)字符串有幾個(gè)指定的子串 :strings.Count("ceheese", "e")//4
⑩不區(qū)分大小寫的字符串比較:fmt.Println(strings.EqualFold("abc."Abc"))// true
(==是區(qū)分字母大小寫的)
①返回子串在字符串第一次出現(xiàn)的index值,如果沒有返回-1 :
strings.Index("NLT_abc", "abc")// 4
②返回子串在字符串最后一次出現(xiàn)的index,如沒有返回-1 :
?strings.LastIndex("go golang","go")//3
③將指定的子串替換成另外一個(gè)子串: strings.Replace("go go hello" , "go" , "go語(yǔ)言", n)n可以指定你希望替換幾個(gè),如果n=-1表示全部替換
④按照指定的某個(gè)字符,為分割標(biāo)識(shí),將一個(gè)字符串拆分成字符串 strings.Split("hello,wrold.ok", ",")
⑤將字符串的字母進(jìn)行大小寫的轉(zhuǎn)換: strings.ToLower("Go")ll go strings.ToUpper("Go")// GO
⑥將字符串左右兩邊的空格去掉:strings.TrimSpace(" tn a lone gopher ntrm ")
⑦將字符串左右兩邊指定的字符去掉:strings.Trim("! hello! ", " !")
⑧將字符串左邊指定的字符去掉:strings.TrimLeft("! hello! ", " !")
⑨將字符串右邊指定的字符去掉: strings.TrimRight("! hello! "," !")
⑩判斷字符串是否以指定的字符串開頭: strings.HasPrefix("ftp://192.168.10.1" , "ftp")//true
①判斷字符串是否以指定的字符串結(jié)束: strings.HasSuffix("NLT_abc.jipg" , "abc")//false
?
時(shí)間和日期:
①導(dǎo)入time包
②獲取信息:now := time.Now( ) ?now.Minute() ?now.Year()
③格式化日期:
A.Printf或SPrintf
?

B.time.Format( )
?

④時(shí)間的常量:得到100毫秒:100*time.Millisecond
?

⑤結(jié)合Sleep使用時(shí)間常量:time.sleep(time.Millisecond* 100)
⑥time的Unix和UnixNano的方法
func (t Time) Unix( ) int64:
從時(shí)間點(diǎn)January 1,1970 UTC到時(shí)間點(diǎn)t所經(jīng)過的時(shí)間(單位秒)
func (t Time) UnixNano( ) int64:
從時(shí)間點(diǎn)January 1, 1970 UTC到時(shí)間點(diǎn)t所經(jīng)過的時(shí)間(單位納秒)。如果納秒為單位的unix時(shí)間超出了int64能表示的范圍,結(jié)果是未定義的。注意這就意味著Time零值調(diào)用UnixNano方法的話,結(jié)果是未定義的。
?
內(nèi)置函數(shù)
這些函數(shù)可直接使用,稱為Go的內(nèi)置函文檔:https://studygolang.com/pkgdoc -> builtin。
①len:求長(zhǎng)度,比如string、array、slice、map、channel。
②new:分配內(nèi)存,主要分配值類型,比如int、float32,struct ...返回的是指針。
③make:分配內(nèi)存,主要分配引用類型,比如channel、map、slice。
?
錯(cuò)誤處理
①Go語(yǔ)言不支持try…catch…finally這種處理。
②Go中引入的處理方式為:defer,panic,recover。
Go中可以拋出一個(gè)panic的異常 → 在defer中通過recover捕獲這個(gè)異常 → 正常處理。
?

③進(jìn)行錯(cuò)誤處理后,程序不會(huì)輕易掛掉,如果加入預(yù)警代碼,就可以讓程序更加的健壯。
?

自定義錯(cuò)誤:使用errors.New和panic內(nèi)置函數(shù)。
① errors.New("錯(cuò)誤說明"),會(huì)返回一個(gè)error類型的值,表示一個(gè)錯(cuò)誤
② panic內(nèi)置函數(shù),接收一個(gè)interface{}類型的值(也就是任何值了)作為參數(shù)??梢越邮?error類型的變量,輸出錯(cuò)誤信息,并退出程序。
?

?