天天看點

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P63 今日内容

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P64 初識接口類型

接口是一種類型,結構體也是一種類型,差別其他基本類型,可以展示多元度的資料

2021/8/28 老男孩帶你21周搞定Go語言 (四)

da誰就會speak,但是這樣寫就限定了dog類型,cat就傳不進去了

2021/8/28 老男孩帶你21周搞定Go語言 (四)

go語言裡不關心一個變量是什麼類型,隻關心能調用的它的什麼方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

那這個函數就要限定傳進來的類型有speak方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

接口就是解決這個問題,限制傳遞進來的變量方法。

像類似的例子在我們程式設計過程中會經常遇到:

比如一個網上商城可能使用支付寶、微信、銀聯等方式去線上支付,我們能不能把它們當成支付方式來處理呢?

比如三角形,四邊形,圓形都能計算周長和面積,我們能不能把它們當成"圖形*來處理呢?

比如銷售、行政程式員都船計算月薪,我們能不能把他們當成員工"來處理呢?

Go語言中為了解決類似上面的問題,就設計了接口這個概念。接口差別于我們之前所有的具體類型,接口是一種抽象的類

型。當你看到一個接口類型的值時,你不知道它是什麼,唯一知道的是通過它的方法能做什麼。

2021/8/28 老男孩帶你21周搞定Go語言 (四)

接口是一種特殊的類型,規定了變量應該有哪些方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

如何使用,類型名可以寫到參數裡,函數裡接收一個speaker類型的變量

2021/8/28 老男孩帶你21周搞定Go語言 (四)

cat和dog都有speak方法,都能當作speaker類型的變量,這個speak類型比較特别,隻規定了你的結構體和變量有什麼方法,必須要有一個speak方法,隻要實作了speak方法都是speaker類型

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這樣就實作了speaker作為一個特殊的類型,隻規定了你要有什麼方法,沒有speak方法,就不是speaker類型的變量,不能當作參數傳進去

2021/8/28 老男孩帶你21周搞定Go語言 (四)

接口隻是一種類型,裡面是限制别人要實作的什麼方法,也叫方法簽名,可有多個

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

造一個run方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

drive函數接收一個car類型的變量,car類型是一個接口類型,不管什麼結構體,隻要有run方法就能是car類型

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

這種适合在不管後端存儲什麼,隻要提供增删改查接口就行,遇到不同類型有統一方法,就可以使用接口類型

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P65 接口的定義與實作

限制力變量有哪些方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

定義,隻要是類型就用type關鍵字來定義,用來給變量,參數,傳回值等設定類型。

2021/8/28 老男孩帶你21周搞定Go語言 (四)

接口的實作

一個變量如果實作了接口中規定的所有的方法,那麼這個變量就實作了這個接口,可以稱為這個接口類型的變量。

比如baoshijie可以稱為car類型的變量

2021/8/28 老男孩帶你21周搞定Go語言 (四)

speaker能接收cat,dog,因為隻要滿足了接口類型限制的方法就可以稱為接口類型的變量。可以把接口類型當作一個普通的類型來使用

2021/8/28 老男孩帶你21周搞定Go語言 (四)

隻要實作了speak的方法,都能滿足接口類型

2021/8/28 老男孩帶你21周搞定Go語言 (四)

go語言現在是面向接口的概念,面向對象的概念是屬性和資料放在一個類裡,在go裡引出了一個接口,不關心屬性和資料,隻要實作了接口就可以。

接口是一種類型,限制規定了你類型需要實作的方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

再寫一個例子,動物接口需要有move和eat方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

貓也需要實作這樣的方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這樣實作的就不是同一個方法,不滿足接口

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這樣貓就實作了接口

2021/8/28 老男孩帶你21周搞定Go語言 (四)

動物是一個接口類型,隻要實作接口裡的所有方法,對應的變量就可以存在animal裡

2021/8/28 老男孩帶你21周搞定Go語言 (四)

調用方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

chicken現在不滿足接口條件,不能讓接口類型變量接收

2021/8/28 老男孩帶你21周搞定Go語言 (四)

修改eat方法函數

2021/8/28 老男孩帶你21周搞定Go語言 (四)

定義什麼類型就是什麼類型,不會做類型轉換

2021/8/28 老男孩帶你21周搞定Go語言 (四)

其實接口類型變量分為兩部分,上面存類型,下面存值,比如cat要存到a1裡,bc裡就有兩個次元的資訊,類型,具體的值

2021/8/28 老男孩帶你21周搞定Go語言 (四)

接口類型存儲的分兩部分,類型和值,剛才列印的類型,就是上面的這個類型,這樣就可以存任何類型,不單是一個類型

2021/8/28 老男孩帶你21周搞定Go語言 (四)

接口可以存任何類型,值,初始的适合都是nil空,

2021/8/28 老男孩帶你21周搞定Go語言 (四)

最開始的動态類型是nil,動态值也是nil,剩下的就是存引用類型

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P66 指針接收者實作接口和值接收者實作接口的差別

2021/8/28 老男孩帶你21周搞定Go語言 (四)

可以用值接收者,也可以用指針接收者

2021/8/28 老男孩帶你21周搞定Go語言 (四)

使用值接收者

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這是使用值接收者實作了接口的所有方法,c2是指針,c1是值

2021/8/28 老男孩帶你21周搞定Go語言 (四)

一個是值,一個是指針

2021/8/28 老男孩帶你21周搞定Go語言 (四)

用指針接收者去實作接口,實作animal接口的是cat的指針類型,值是存不進去的,隻能存位址

2021/8/28 老男孩帶你21周搞定Go語言 (四)

使用值接收者實作接口和使用指針接收者實作接口的差別?

使用值接收者,不管儲存的是結構體還是結構體的指針都能存進去。

使用指針接收者,就隻能傳指針。

大部分用的是指針接收者

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P67 實作多個接口和接口嵌套

同一個結構體可以實作多個接口,貓實作了move和eater接口

2021/8/28 老男孩帶你21周搞定Go語言 (四)

接口可以嵌套

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P68 空接口

如果一個變量實作了接口裡的所有方法,如果沒有方法,任何類型都實作了這個接口

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這就是一個空接口的類型

2021/8/28 老男孩帶你21周搞定Go語言 (四)

空接口沒有必要起名字,所有類型都實作了空接口,也就是任意類型的變量都能儲存到空接口中。

2021/8/28 老男孩帶你21周搞定Go語言 (四)

當不知道要儲存什麼類型的時候,可以寫一個空接口。

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

前面是類型,後面是value

2021/8/28 老男孩帶你21周搞定Go語言 (四)

空接口可以存儲任意類型的值,那如何擷取存儲的資料

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

如何拿到值,就需要類型斷言,斷言就是猜的意思

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

猜不對還需要繼續猜,可以試試switch

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

試試switch

2021/8/28 老男孩帶你21周搞定Go語言 (四)

進行判斷

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

隻有當兩個或兩個以上的具體類型必須以相同的方式進行處理時才需要定義皆苦。不要為了接口而寫接口,那樣隻會增加不必要的抽象,導緻不必要的運作時損耗。

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P69 package相關

go語言包,也是組織go語言的一個機關,比如fmt包,os包,io包

2021/8/28 老男孩帶你21周搞定Go語言 (四)

定義一個包,包了裡就提供一個add函數,包裡的變量名需要首字母大寫,才能被外部引用

2021/8/28 老男孩帶你21周搞定Go語言 (四)

要導入這個包,需要指定路徑,隻有main包才能編譯成一個可執行檔案,預設目錄名當作一個包名

2021/8/28 老男孩帶你21周搞定Go語言 (四)

如果檔案夾名和包名不一樣,可以起一個别名,後面是路徑名

2021/8/28 老男孩帶你21周搞定Go語言 (四)

一個包假如要引用另一個包裡的辨別符(如變量,常量,類型,函數等),辨別符的首字母必須大寫

2021/8/28 老男孩帶你21周搞定Go語言 (四)

包的導入就是import語句,導入的包名要用雙引号括一起。

2021/8/28 老男孩帶你21周搞定Go語言 (四)

儲存以後會自動幫你空一行,代表上面是标準庫,下面是第三方的包

2021/8/28 老男孩帶你21周搞定Go語言 (四)

包名是從$GOPATH/src目錄開始算

2021/8/28 老男孩帶你21周搞定Go語言 (四)

從這個路徑往後寫

2021/8/28 老男孩帶你21周搞定Go語言 (四)

go之前還無法解決引用其他包版本的問題,隻能把包的源代碼下載下傳到本地運作,後面可以用gomod

2021/8/28 老男孩帶你21周搞定Go語言 (四)

禁止循環導入,a導b,b導c,c導a,go編譯的時候,是先從main包找起,然後找到了别人的包,把這裡的代碼和自己的代碼打包成一個整體。

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

比如導入資料庫的包,不用它的方法,用它連結資料庫的那一段代碼,但沒有用到包的任何方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這樣說白了隻執行包裡的init方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)

go語言導入包的時候,會自動觸發init函數的調用。沒有參數,沒有傳回值,不能手動調用,隻能自動調用

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

先執行導入包的語句,再執行main的init

2021/8/28 老男孩帶你21周搞定Go語言 (四)

搜尋到全局變量的聲明後,就會執行init

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這樣就代表先全局聲明變量,再執行int了

2021/8/28 老男孩帶你21周搞定Go語言 (四)

如果導入多個包,每個包都有init函數,那麼這樣的執行順序是什麼順序。

main導入a,a導入b,b導入c,執行的時候需要先執行c的init,然後b的init

2021/8/28 老男孩帶你21周搞定Go語言 (四)

包的路徑從GOPATH/src後面的路徑開始。

要想被别的包調用辨別符必須要首字母大寫。

導入包的時候可以指定别名。

導入包的時候不想要使用包内部的辨別符,需要使用匿名導入。

每個包導入的時候會自動執行一個名為init()的函數,他沒有參數有沒有傳回值,不能手動調用。

多個包都定義了init(),則他們的執行順序見下圖

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P70 為什麼要有日志庫作業

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P71 打開檔案讀内容

os.Open()可以打開一個檔案,傳回的是一個*File ,file類型的指針和一個錯誤err,要關閉檔案需要用close()方法

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

打開檔案其實就是跟作業系統要一個操作接口,需要最後釋放,可以使用defer close

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

這是一個Read方法,接收者,參數,return,[]byte其實是一個位元組的切片

2021/8/28 老男孩帶你21周搞定Go語言 (四)

可以指定讀的長度,下面是簡寫,數組可以切片,這樣代表依次讀128個,讀到切片裡

2021/8/28 老男孩帶你21周搞定Go語言 (四)

如果讀128個,那麼n就是128,

2021/8/28 老男孩帶你21周搞定Go語言 (四)

讀出來的檔案

2021/8/28 老男孩帶你21周搞定Go語言 (四)

寫個for循環,如果要讀128個位元組,已經到末尾了,n就是0,就需要退出,如果有129個位元組,一詞讀128個,剩下1個,那麼n就不等于0,下次再讀就讀不到了

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

隻有129個位元組,第一次讀了128,下次再讀,隻有一個就不滿足條件 ,就不會去讀

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這樣就會去讀,小于128說明,沒讀滿,說明讀完了

2021/8/28 老男孩帶你21周搞定Go語言 (四)

最後一次讀的肯定沒有128

2021/8/28 老男孩帶你21周搞定Go語言 (四)

讀的時候,也可能有各種錯,比如中間檔案被移走了

2021/8/28 老男孩帶你21周搞定Go語言 (四)

固定位元組讀循環是比較low的,還有一種優雅的方式是用bufio,相當于你從磁盤讀檔案,先放到緩沖區裡,再讀到程式裡。

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

NewReade表示新的讀的動作的執行者

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

下面是利用bufio

2021/8/28 老男孩帶你21周搞定Go語言 (四)

建立一個read讀對象,然後for循環即可

2021/8/28 老男孩帶你21周搞定Go語言 (四)

隻讀了一行,因為沒有循環讀

2021/8/28 老男孩帶你21周搞定Go語言 (四)

寫一個for循環,兩種情況退出,讀完了退出,報錯了退出

2021/8/28 老男孩帶你21周搞定Go語言 (四)

現在每一行會多一個空格,println會自帶一個空格

2021/8/28 老男孩帶你21周搞定Go語言 (四)

換成print

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

可以使用ioutil這個包,之前把整個檔案讀出來

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

也是打開檔案,close,建立int64變量,n的大小就是讀的檔案的大小

2021/8/28 老男孩帶你21周搞定Go語言 (四)

肯定也是一個for循環

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P72 檔案寫入

2021/8/28 老男孩帶你21周搞定Go語言 (四)

打開的模式有幾種,wronly隻寫,create建立檔案,rdonly隻讀,trunc清空,windows的perm是沒有用的,linux才有用,0777這樣

2021/8/28 老男孩帶你21周搞定Go語言 (四)

沒有檔案就會報錯

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這些是int類型

2021/8/28 老男孩帶你21周搞定Go語言 (四)

其實是16進制數,這些數都是從上到下往左移動,就可以用位

2021/8/28 老男孩帶你21周搞定Go語言 (四)

16進制數1表示1,2表示2

2021/8/28 老男孩帶你21周搞定Go語言 (四)

40轉二進制就是這樣的

2021/8/28 老男孩帶你21周搞定Go語言 (四)

隻讀和隻寫,要麼是0 ,要麼是1,不能同時出現,位數相或的時候最外位數隻能有一個,隻要有一個為1就是去

2021/8/28 老男孩帶你21周搞定Go語言 (四)

有些肯定是沖突的,

2021/8/28 老男孩帶你21周搞定Go語言 (四)

隻能傳一個int,因為可以每個二進制位代表不同的操作

2021/8/28 老男孩帶你21周搞定Go語言 (四)

是以可以把好多的參數進行位于,寫到一個參數裡

|位于操作

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

位與判斷在幹嘛

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

隻讀,沒有就建立,有的話就追加

2021/8/28 老男孩帶你21周搞定Go語言 (四)

write寫的是位元組,writestring寫的是字元串

2021/8/28 老男孩帶你21周搞定Go語言 (四)

最後一定要關閉檔案,沒有就會建立檔案

2021/8/28 老男孩帶你21周搞定Go語言 (四)

寫入裡面的内容

2021/8/28 老男孩帶你21周搞定Go語言 (四)

試試清空

2021/8/28 老男孩帶你21周搞定Go語言 (四)

每次都會清空了寫内容

2021/8/28 老男孩帶你21周搞定Go語言 (四)

bufio建立一個寫對象

2021/8/28 老男孩帶你21周搞定Go語言 (四)

記得flush,因為之前是寫在緩存裡的

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

iouitil.WriteFile,往檔案寫東西

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

實作一個copy指令,讀檔案寫到另一個檔案裡

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P73 使用bufio擷取使用者輸入

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這個scanln相當于讀到空白字元,空格或者回車

2021/8/28 老男孩帶你21周搞定Go語言 (四)

建立一個函數,Readerstring 可以一直讀到換行符

2021/8/28 老男孩帶你21周搞定Go語言 (四)

現在就可以讀取到空格以後的

2021/8/28 老男孩帶你21周搞定Go語言 (四)

這兩個都相當于傳了檔案,不管是os.stdin,還是filedb,都能告訴函數裡面有什麼東西,是以這兩個都需要去實作一個讀東西的方法。

2021/8/28 老男孩帶你21周搞定Go語言 (四)

是以newReader()參數就是一個接口類型

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)

io.reader就是一個接口類型,不管是标準輸入,網絡還是檔案,都可以讀,隻要實作reader方法即可。

2021/8/28 老男孩帶你21周搞定Go語言 (四)

P74日志庫作業需求

需要分級别,還要寫入檔案句柄

2021/8/28 老男孩帶你21周搞定Go語言 (四)
2021/8/28 老男孩帶你21周搞定Go語言 (四)