Go語言學(xué)習(xí)教程(十二)

一法瑟、斷言

* 只要實(shí)現(xiàn)了接口的全部方法就認(rèn)為這個(gè)類型屬于接口類型,如果編寫一個(gè)接口,這個(gè)接口中沒有任何方法,這時(shí)認(rèn)為所有類型都實(shí)現(xiàn)了這個(gè)接口.所以Go語言中interface{}代表任意類型

* 如果interface{}作為方法參數(shù)就可以接收任意類型,但是在程序中有時(shí)需要知道這個(gè)參數(shù)到底是什么類型,這個(gè)時(shí)候就需要使用斷言

* 斷言使用時(shí)担巩,使用interface{}變量點(diǎn)括號(hào),括號(hào)中判斷是否屬于的類型

?? ?i interface{}

?? ?i.(Type)

* 斷言的兩大作用:

????* 判斷是否是指定類型

????* 把interface{}轉(zhuǎn)換為特定類型

* 斷言可以有一個(gè)返回值坦弟,如果判斷結(jié)果是指定類型返回變量值,如果不是指定類型則報(bào)錯(cuò)

?? ?func demo(i interface{}){

?????? ?result:=i.(int)

?????? ?fmt.Println(result)

?? ?}

?? ?func main() {

?????? ?/*

?????? ?參數(shù)是456時(shí),程序運(yùn)行正常,輸出456

?????? ?參數(shù)是false時(shí)報(bào)錯(cuò):

????????panic: interface conversion: interface {} is bool, not int

???? ?? ?*/

?????? ?demo(456)

?? ?}

* 斷言也可以有兩個(gè)返回值,這時(shí)無論是否是指定類型都不報(bào)錯(cuò).

????* 第一個(gè)參數(shù):

????????* 如果正確:返回值變量值

????????* 如果錯(cuò)誤:返回判斷類型的默認(rèn)值

????* 第二個(gè)參數(shù):

????????* 返回值為bool類型,true表示正確,false表示錯(cuò)誤

?? ?func demo(i interface{}) {

????? ??result, ok := i.(int)

????? ??fmt.Println(result, ok)

?? ?}

?? ?func main() {

?????? ?/*

?????? ?參數(shù)是456時(shí),程序運(yùn)行正常,輸出456????true

?????? ?參數(shù)是字符串"abc"時(shí)程序運(yùn)行正常,輸出0 false

???? */

?????? ?demo("abc")

?? ?}

二走诞、錯(cuò)誤

* 在程序執(zhí)行過程中出現(xiàn)的不正常情況稱為錯(cuò)誤

* Go語言中使用builtin包下的error接口作為錯(cuò)誤類型,官方源碼定義如下

????* 只包含了一個(gè)方法,方法返回值是string,表示錯(cuò)誤信息

?? ?type error interface {

?????? ?Error() string

?? ?}

* Go語言中錯(cuò)誤都作為方法/函數(shù)的返回值,因?yàn)镚o語言認(rèn)為使用其他語言類似try...catch這種方式會(huì)影響到程序結(jié)構(gòu)

* 在Go語言標(biāo)準(zhǔn)庫的errors包中提供了error接口的實(shí)現(xiàn)結(jié)構(gòu)體errorString,并重寫了error接口的Error()方法.額外還提供了快速創(chuàng)建錯(cuò)誤的函數(shù)

* 如果錯(cuò)誤信息由很多變量(小塊)組成,可以借助fmt.Errorf("verb",...)完成錯(cuò)誤信息格式化,因?yàn)榈讓舆€是errors.New()

三势决、自定義錯(cuò)誤

* 使用Go語言標(biāo)準(zhǔn)庫創(chuàng)建錯(cuò)誤,并返回

?? ?func demo(i, k int) (d int, e error) {

?????? ?if k == 0 {

????????? ??e = errors.New("初始不能為0")

?????????? ?d=0

?????????? ?return

????? ??}

?????? ?d = i / k

?????? ?return

?? ?}

?? ?func main() {

????? ??result,error:=demo(6,0)

?????? ?fmt.Println(result,error)

?? ?}

* 如果錯(cuò)誤信息由多個(gè)內(nèi)容組成,可以使用下面實(shí)現(xiàn)方式

?? ?func demo(i, k int) (d int, e error) {

?????? ?if k == 0 {

?????????? ?e = fmt.Errorf("%s%d和%d", "除數(shù)不能是0,兩個(gè)參數(shù)分別是:", i, k)

?????????? ?d = 0

?????????? ?return

????? ??}

?????? ?d = i / k

?????? ?return

?? ?}

?? ?func main() {

?????? ?result, error := demo(6, 0)

?????? ?fmt.Println(result, error)

?? ?}

四熔恢、Go語言中錯(cuò)誤處理方式

* 可以忽略錯(cuò)誤信息,使用占位符

?? ?result, _ := demo(6, 0)

* 使用if處理錯(cuò)誤,原則上每個(gè)錯(cuò)誤都應(yīng)該解決

func main() {

????result, error := demo(6, 0)

????if error != nil {

????????fmt.Println("發(fā)生錯(cuò)誤", error)

????????return

????}

????fmt.Println("程序執(zhí)行成功,結(jié)果為:", result)

}

五轻姿、defer使用

* Go語言中defer可以完成延遲功能,當(dāng)前函數(shù)執(zhí)行完成后執(zhí)行defer功能

* defer最常用的就是關(guān)閉連接(數(shù)據(jù)庫連接,文件等)可以打開連接后代碼緊跟defer進(jìn)行關(guān)閉,后面在執(zhí)行其他功能

????* 在很多語言中要求必須按照順序執(zhí)行,也就是必須把關(guān)閉代碼寫在最后,但是經(jīng)常會(huì)忘記關(guān)閉導(dǎo)致內(nèi)存溢出,而Golang中的defer很好的解決了這個(gè)問題.無論defer寫到哪里都是最后執(zhí)行

func main() {

???fmt.Println("打開連接")

???defer func(){

??????fmt.Println("關(guān)閉連接")

???}()

???fmt.Println("進(jìn)行操作")

???//輸出:打開連接 進(jìn)行操作 關(guān)閉連接

}

* 多重defer采用棧結(jié)構(gòu)執(zhí)行,先產(chǎn)生后執(zhí)行

* 在很多代碼結(jié)構(gòu)中都可能出現(xiàn)產(chǎn)生多個(gè)對(duì)象,而程序希望這些對(duì)象倒序關(guān)閉,多個(gè)defer正好可以解決這個(gè)問題

func main() {

???fmt.Println("打開連接A")

???defer func(){

??????fmt.Println("關(guān)閉連接A")

???}()

???fmt.Println("打開連接B")

???defer func(){

??????fmt.Println("關(guān)閉連接B")

???}()

???fmt.Println("進(jìn)行操作")

???//輸出:打開連接A 打開連接B 進(jìn)行操作 關(guān)閉連接B 關(guān)閉連接A

}

* defer與return同時(shí)存在時(shí),要把return理解成兩條執(zhí)行結(jié)合(不是原子指令),一個(gè)指令是給返回值賦值,另一個(gè)指令返回跳出函數(shù)

* defer和return時(shí)整體執(zhí)行順序

????* 先給返回值賦值

????* 執(zhí)行defer

????* 返回跳出函數(shù)

* 沒有定義返回值接收變量,執(zhí)行defer時(shí)返回值已經(jīng)賦值

func f() int{

????i:=0

????defer func(){

????????i=i+2

????}()

????return i

}

func main() {

????fmt.Println(f())//輸出:0

}

* 聲明接收返回值變量,執(zhí)行defer時(shí)修改了返回值內(nèi)容.

????* 由于return后面沒有內(nèi)容,就無法給返回值賦值,所以執(zhí)行defer時(shí)返回值才有內(nèi)容

func f() (i int){

????defer func(){

????????i=i+2

????}()

????return

}

func main() {

????fmt.Println(f())//輸出:2

}

六筑累、panic

* panic是builtin中函數(shù)

* panic有點(diǎn)類似于其他編程語言的throw,拋出異常.當(dāng)執(zhí)行到panic后終止剩余代碼執(zhí)行.并打印錯(cuò)誤棧信息

* 注意panic不是立即停止程序(os.Exit(0)),defer還是執(zhí)行的.

七袱蜡、recover

* recover()表示恢復(fù)程序的panic(),讓程序正常運(yùn)行

* recover()是和panic(v)一樣都是builtin中函數(shù),可以接收panic的信息,恢復(fù)程序的正常運(yùn)行

* recover()一般用在defer內(nèi)部,如果沒有panic信息返回nil,如果有panic,recover會(huì)把panic狀態(tài)取消

* recover()只能恢復(fù)當(dāng)前函數(shù)級(jí)或當(dāng)前函數(shù)調(diào)用函數(shù)中的panic(),恢復(fù)后調(diào)用當(dāng)前級(jí)別函數(shù)結(jié)束,但是調(diào)用此函數(shù)的函數(shù)可以繼續(xù)執(zhí)行.

* panic會(huì)一直向上傳遞,如果沒有recover()則表示終止程序,但是碰見了recover(),recover()所在級(jí)別函數(shù)表示沒有panic,panic就不會(huì)向上傳遞

八、os包結(jié)構(gòu)介紹

* Go語言標(biāo)準(zhǔn)庫中os包提供了不依賴平臺(tái)的操作系統(tǒng)接口

* 設(shè)計(jì)為Unix風(fēng)格的疼阔,而錯(cuò)誤處理是go風(fēng)格的,失敗的調(diào)用會(huì)返回錯(cuò)誤值而非錯(cuò)誤碼戒劫。通常錯(cuò)誤值里包含更多信息

* os包及子包功能

?? ?-- os 包

??? ??--os/exec 包,負(fù)責(zé)執(zhí)行外部命令.

???? ?--os/signal對(duì)輸入信息的訪問

???? ?--os/user 通過名稱或ID????查詢用戶賬戶

* 在os/user中提供了User結(jié)構(gòu)體,表示操作系統(tǒng)用戶

????* Uid 用戶id

????* Gid 所屬組id

????* Username 用戶名

????* Name 所屬組名

????* HomeDir 用戶對(duì)應(yīng)文件夾路徑

* 在os/user中的Group表示用戶所屬組

????* Gid 組的id

????* Name 組的名稱

* 整個(gè)os/user包中內(nèi)容比較少,提供了兩個(gè)錯(cuò)誤類型和獲取當(dāng)前用戶,查找用戶

* 可以獲取當(dāng)前用戶或查找用戶后獲取用戶信息

???// 獲取當(dāng)前登錄用戶

???// u,_:=user.Current()

? ?// Lookup()參數(shù)是用戶名,按照用戶名查找指定用戶對(duì)象

? ?// 注意:必須使用完整名稱不可以只寫zhang

???u, _ := user.Lookup(`LAPTOP-M7D47U95\zhang`)

???fmt.Println(u.Name)

???fmt.Println(u.Gid)

???fmt.Println(u.HomeDir)

???fmt.Println(u.Uid)

???fmt.Println(u.Username)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末半夷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子迅细,更是在濱河造成了極大的恐慌巫橄,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茵典,死亡現(xiàn)場(chǎng)離奇詭異湘换,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)统阿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門彩倚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人扶平,你說我怎么就攤上這事帆离。” “怎么了结澄?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵哥谷,是天一觀的道長。 經(jīng)常有香客問我麻献,道長们妥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任勉吻,我火速辦了婚禮监婶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘齿桃。我一直安慰自己惑惶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布源譬。 她就那樣靜靜地躺著集惋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪踩娘。 梳的紋絲不亂的頭發(fā)上刮刑,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音养渴,去河邊找鬼雷绢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛理卑,可吹牛的內(nèi)容都是我干的翘紊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼藐唠,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼帆疟!你這毒婦竟也來了鹉究?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤踪宠,失蹤者是張志新(化名)和其女友劉穎自赔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柳琢,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绍妨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了柬脸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片他去。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖倒堕,靈堂內(nèi)的尸體忽然破棺而出灾测,到底是詐尸還是另有隱情,我是刑警寧澤涩馆,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布行施,位于F島的核電站,受9級(jí)特大地震影響魂那,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜稠项,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一涯雅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧展运,春花似錦活逆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至埂软,卻和暖如春锈遥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勘畔。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工所灸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人炫七。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓爬立,卻偏偏與公主長得像,于是被迫代替她去往敵國和親万哪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子侠驯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容