1. 程式人生 > >Golang學習筆記 方法和介面

Golang學習筆記 方法和介面

在程式語言中,方法和函式的概念需要搞清楚。函式指的是一個封裝的程式碼塊,我們可以直接呼叫它,並返回結果。而方法其實也是一種函式,只不過方法需要和某個物件繫結。Golang並沒有類的概念,不過仍然有方法和介面這些概念。

方法

方法接收者

方法接收者是一個特殊引數,給函式指定了這個引數之後,函式就成為方法了。這個特性有點像Kotlin和C#中的擴充套件方法,定義了帶有接收者的方法之後,接收者這個型別就好像定義了這個方法一樣,我們可以直接在該型別上呼叫方法。這在功能上,和麵向物件的概念是很類似的。

例如下面這樣,定義了一個汽車結構,然後定義了一個接受者方法。然後就可以用面向物件的方式來呼叫這個方法了。

func Method() {
    //方法接收者
    car := Car{id: 1}
    car.beep()
}

type Car struct {
    id int
}

func (car Car) beep() {
    fmt.Printf("Car %v beeps", car.id)
}

接收者方法也有一些限制,這也是它和擴充套件方法之間的區別。接收者方法的接受者型別,必須和接收者方法定義在同一個包中。所以很多非自定義的型別,以及基本型別都不能當做接收者的型別。當然也可以投機取巧,在自己的包中重新為這些型別取個名字即可。

//把基本型別重新定義一下,就可以當做接收者型別了
type MyString string func (str MyString) hello() { fmt.Println("hello" + str) }

指標接收者

接收者的型別可以是指標,如果希望在接收者方法中修改接收者的屬性,就需要指標型別了。下面的程式碼對Car結構體添加了兩個方法,第一個由於沒有指標型別,所以不會修改原始結構體中的值;而第二個方法會修改汽車的id。

func (car Car) beep() {
    fmt.Printf("Car %v beeps", car.id)
}

func (car Car) changeId() {
    car
.id += 1 } func (car *Car) changeRealId() { car.id += 1 }

介面

聽起來很奇怪,如果Golang沒有型別,為什麼會有介面的概念?讓我們來看看Golang如何解決這些問題。

定義介面

在Golang中,介面就是一組方法簽名的集合。下面就定義了一個介面。

type ICar interface {
    beep()
    drive(driver string)
}

實現介面

在Golang中,其實並沒有“實現介面”這一說法。在Golang中介面是隱式實現的,也就是說我們不需要implements這些關鍵字。只要一個型別的接收者方法和介面中定義的方法一致,Golang就認為這個型別實現了該介面。下面是一個簡單的例子。

func Interface() {
    car := MyCar{id: 1}
    var icar ICar = car
    icar.beep()
    icar.drive("yitian")
}

type ICar interface {
    beep()
    drive(driver string)
}

type MyCar struct {
    id int
}

func (car MyCar) beep() {
    fmt.Printf("car %v beeps\n", car.id)
}
func (car MyCar) drive(driver string) {
    fmt.Printf("%v drives car %v\n", driver, car.id)
}

空介面

什麼方法都沒定義的介面就是空介面。根據Golang的概念,空介面被任何型別隱式實現,所以空介面可以容納任何型別。

//空介面可以作為任何型別使用
type Everything interface {
}

var e Everything = "123"
fmt.Println(e)

型別細化

定義和實現介面是一個型別泛化的過程,在這個過程中,我們抹消掉了型別特有的部分,讓型別公有的部分能夠統一利用。不過有時候需要反過來,將一個介面物件轉換為原始的具體類,讓我們能夠獲取更具體的行為。

現在來看看在Golang中,這件事情應該怎麼做。再次使用上面定義的型別。可以看到和C系語言的括號強轉方式不同,在Golang中是.(T)型別的語法。

//特化型別
myCar := icar.(MyCar)
//myCar是MyCar型別變數
myCar.beep()

這個語法還有一個攜帶一個成功標誌的版本 t, ok := i.(T)。當成功標誌為真時,表示成功將介面轉換為具體型別,否則表示該介面不是具體型別的例項。

如果要進行多次判斷,可以利用switch語句。下面是一個例子。

func testType(i interface{}) {
    switch i.(type) {
    case string:
        fmt.Printf("%v is string\n", i)
    case int:
        fmt.Printf("%v is int\n", i)
    default:
        fmt.Printf("%v is interface{}\n", i)
    }
}

對這個方法呼叫多次,可以看到針對不同的型別,方法會返回不同結果。

//型別檢測
testType("abc")
testType(123)
testType(nil)

相關推薦

Golang學習筆記 方法介面

在程式語言中,方法和函式的概念需要搞清楚。函式指的是一個封裝的程式碼塊,我們可以直接呼叫它,並返回結果。而方法其實也是一種函式,只不過方法需要和某個物件繫結。Golang並沒有類的概念,不過仍然有方法和介面這些概念。 方法 方法接收者 方法接收者是

Golang學習筆記--ArraySlice

目錄   Reference Array Slice slice的建立 Slice常用操作 reslice append函式 copy函式 range遍歷 Reference https://blog.golang.org/go-sl

golang學習筆記---函式、方法介面

函式:對應操作序列,是程式的基本組成元素。 函式有具名和匿名之分:具名函式一般對應於包級的函式,是匿名函式的一種特例,當匿名函式引用了外部作用域中的變數時就成了閉包函式,閉包函式是函數語言程式設計語言的核心。方法是綁 定到一個具體型別的特殊函式,Go語言中的方法是依託於型別的,必須在編譯時靜態繫結 介面

golang學習筆記---函數、方法接口

動態綁定 多個 依賴 find 輸出 ack range 支持 不定 函數:對應操作序列,是程序的基本組成元素。 函數有具名和匿名之分:具名函數一般對應於包級的函數,是匿名函數的一種特例,當匿名函數引用了外部作用域中的變量時就成了閉包函數,閉包函數是函數式編程語言的核心。方

Golang學習筆記1-組合介面

主要內容 1.組合 2.介面 3.常見問題 4.總結 1.組合 Golang中沒有OOP中繼承的概念,取而代之的是組合,同樣起到屬性和方法繼承 的作用,特別是匿名組合,其表現形式和繼承的行為類似,但是卻有很多不同的地方,相對於繼承、多型這些典型的OOP思

[java學習筆記]IteratorIterable介面

    Iterator和Iterable都是java的迭代器介面,二者既有區別又有聯絡,下面從介面定義,實現和方法呼叫三方面分析兩介面的關係和使用方法。 1.介面定義 1.1 Iterable     Iter

golang學習筆記(一)——golang基礎相關資料結構

小白前端一枚,最近在研究golang,記錄自己學習過程中的一些筆記,以及自己的理解。 go中包的依賴管理 go中的切片 byte 和 string go中的Map go中的struct結構體 go中的方法 go中的interface介面 inter

MongoDB學習筆記~為IMongoRepository介面添加了增刪改方法,針對官方驅動

回到目錄 上一講說了MongoDB官方驅動的查詢功能,這回說一下官方驅動的增刪改功能,驅動在升級為2.0後,相應的insert,update和delete都只有了非同步版本(或者叫並行版本),這當然也是跟著.net走的正方向,大事所趨,但有時,我們的前臺已經使用同步方式實現了,為了不改變前臺程式碼,所以,後

MongoDB學習筆記~為IMongoRepository介面新增分頁取集合的方法

回到目錄 對於資料分頁,我們已經見的太多了,幾乎每個列表頁面都要用到分頁,這已經成了一種定理了,在進行大資料展示時,如果不去分頁,而直接把資料載入到記憶體,這簡直是不可以去相向的,呵呵,在很多ORM工具中都對分頁有了更好的支援,如LINQ裡有大家熟悉的take和skip,而在MongoDB裡也有這種概念,它

MongoDB學習筆記~為IMongoRepository介面添加了排序表示式樹,針對官方驅動

回到目錄 MongoDB的官方驅動,語法更好,更強 之前寫過關於IMongoRepository倉儲的文章,在mongodb的驅動選擇上使用了NoRM,但是進行$ref引用型別導航時出現了問題,它對引用型別屬性支援不是很好,還是使用幾年前的泛型技術而沒有使用Attribute,在這個方面官方驅動做的更好,

[Golang學習筆記] 06 程序實體3 類型斷言類型轉換

問題 怎麽 values ima spa 極客 內部 png nta 類型斷言: 語法:<目標類型的值>,<布爾參數> := <表達式>.( 目標類型 ) // 安全類型斷言<目標類型的值> := <表達式>.(

[Golang學習筆記] 07 陣列切片

01-06回顧: Go語言開發環境配置, 常用原始碼檔案寫法, 程式實體(尤其是變數)及其相關各種概念和程式設計技巧:   型別推斷,變數重宣告,可重名變數,型別推斷,型別轉換,別名型別和潛在型別 陣列: 陣列型別的值的長度是固定的,在宣告陣列的時候,長度必須給定,並且在之後不

iPhone開發學習筆記001——Xib介面上的控制元件與程式碼的相互關聯方法

(注:環境Mac OS X Lion 10.7.3 + Xcode 4.2.1 + iOS SDK 5.0.) 比如工程中添加了一個UIViewController的sub class,新建的時候選中“With XIB for user interface”,則新建完成會同

比較完善的學習流程方法Java學習中越到的所有問題

lag 編程 算法 ron java學習 XML col add servlet Java是一門面向對象編程語言,Java語言具有封裝、繼承、多態三個特性,這三個特征又使得Java語言比其他編程語言的功能更加強大強大、用起來更加簡單。Java語言作為靜態面向對象編程語言的代

說一說本人對linux系統學習方法經驗

linux 百度 應用程序 操作系統 多線程 相信大夥都聽說過linux系統,然而對於這個系統,總使讓新手感覺茫然,諾達的系統。下面是一段百度中的介紹:Linux系統是一套開源的並且能夠自由傳播的類似與Unix操作系統,是一個基於POSIX和UNIX的多任務、多用戶、支持多線程和多CPU的

(一)Oracle學習筆記—— 表表空間

最大 更改 默認 oracle spa mil 步驟 font lte 1. 表空間 一個數據庫可以有多個表空間,一個表空間裏可以有多個表。表空間就是存多個表的物理空間;可以指定表空間的大小位置等。 1.1 創建表空間語句 create tablespace t

python學習筆記列表元組(三)

python列表(list)是Python以及其他語言中最常用到的數據結構之一。Python使用使用中括號 [ ] 來解析列表。列表是可變的(mutable)——可以改變列表的內容。對應操作:1、查([]切片操作) name = [‘tom‘,‘張三‘,‘joker‘,‘李四‘] print(name[2])

學習筆記---buffercache的區別

cache一.概念buffer:緩沖區,一個用於存儲速度不同步的設備或優先級不同的設備之間傳輸數據的區域。cache: 緩存,位於CPU與主內存間的一種容量較小但速度很高的存儲器。保存著CPU剛用過或循環使用的一部分數據。二、應用場景buffer:由各種進程分配,被用在輸入隊列等方面。cache: 用在磁盤的

Maven學習筆記—安裝配置

src 自己 修改 分享 另一個 window 關於 1.3 頁面 Maven的安裝和配置 1 在windows上安裝maven 1.1 下載maven 訪問maven的下載頁面:http://maven.apache.org/download.cgi,選擇版本下載即可。

Python 學習筆記 -- 類實例

isdigit 特殊 .... 方法 raise fun angle 總結 area 1 #創建一個類,類是一種具有相同屬性和方法的抽象 2 #創建類需要使用class關鍵字,並且定義方法時,方法的第一個參數是self 3 class Student(object)