Golang編程基礎第二篇——Golang的面向對象

Golang作爲一種“更好的C語言“,提供了面向對象編程思想的支持。

這一篇是上一篇的補充,主要闡述了go語言面向對象的一些特性,值傳遞和指針傳遞在go語言的運用,並補充了一些golang的數據類型

目錄

一,Golang面向對象和類型系統

二,Golang的this指針

三,golang的值語義和引用語義

四,結構體


一,Golang面向對象和類型系統

在go中你可以爲任何類型添加相應的方法:

//爲類型添加方法
type Integer int

//面向對象操作,對象是Integer這個類型的a值
func (a Integer) Less(b Integer) bool {
    return a < b
}

//面向對象調用
func main() {
    var a Integer = 1
    if a.Less(2) {
        fmt.println(a, " Less 2")
    }
}

同時,我們也可以像之前一樣面向過程

type Integer int

func Integer_less(a Integer, b Integer) bool {
    return a < b
}

func main() {
    var a Integer = 1
    if Integer_less(a, 2) {
        fmt.Println(a, " less 2")
    }
}

所以能清楚的看出來兩者的區別 有助於我們讀懂並做好代碼 避免有的時候自己調用自己

二,Golang的this指針

首先我們要知道什麼是this指針

在 C++ 中,每一個對象都能通過 this 指針來訪問自己的地址。this 指針是所有成員函數的隱含參數。因此,在成員函數內部,它可以用來指向調用對象。

在其他語言中比如C#和java,都遵循着C++的慣例,他們的成員方法都有着隱藏的this指針,而python的成員方法中有self參數和this指針作用相同。

在go中沒有隱藏的this指針

這句話的含義是:方法施加的目標(即對象),沒有被隱藏起來;方法施加的目標(即對象)不需要是指針,也不用非得是this。這裏可能有點繞,需要對值傳遞和引用傳遞有一定了解,上節我們知道go和C語言一樣是基於值傳遞,要想改變該變量的指針必須傳遞指針,所以go只有在你需要修改對象的時候,才必須使用指針。比如下面的兩個例子:

//指針傳遞
func (a *Integer) Add(b Integer) {
    *a += b
}

//值傳遞
func (a Integer) Add(b Integer) {
    a += b
}

//驗證
func main() {
    var a Integer = 1
    a.Add(2)
    //指針傳遞結果爲3
    //值傳遞結果爲1
    fmt.Println("a = ", a)
}

三,golang的值語義和引用語義

值語義:

變量賦值後,兩個變量擁有的存儲空間是獨立的,相互之間不影響

引用語義:

變量引用賦值後,兩個變量只有一份的存儲空間,相互之間可以理解爲是別名,操作任意一個變量,就可以認爲是操作另外一個變量,效果完全一樣

b = a    //值類型
b.Modify()    //引用類型

如果b的修改不影響a的值,那麼此類型屬於值類型

如果會影響a的值,那麼此類型爲引用類型

我們可以把go語言所有類型看成是值類型,從這個角度再深入看幾個看起來像引用類型的golang類型,他們都是通過指針傳遞值,所以對於兩個指向同一塊數據的a或者b進行底層數據的修改來說,兩者是互相影響的,比如a[0]=1, 這個是相當於作用於底層市局data

但是若是直接修改a或者b,比如a=[]int{},那麼就相當於a對應的struct的值變了,裏面的指針p變了之後,就相當於指向了另外一個data。這個時候a和b之間的操作就沒有關係了

1. 數組切片

數組切片是指向數組的一個區間

我們複習一下數組切片長這樣:

var slice1 []type = make([]type, len)    //聲明切片長度和類型的數組切片

也可以簡寫爲

slice1 := make([]type, len)    

數組切片本質是一個區間,你可以大致理解爲這樣一個結構:

type slice struct {
    first *T
    len int
    cap int
}

因爲數組切片內部是指向數組的指針,所以可以改變指向數組元素,其類型本身仍是值語義。

2. map

提供鍵值查詢能力,和我們常見的數據結構相同

/* 聲明變量,默認 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函數 */
map_variable := make(map[key_data_type]value_data_type)

/* 你可以講map[k]v表示爲:*/
type Map_k_v struct {
    //...
}

type Map[k]v struct {
    impl *Map_k_v
}

3.channel

執行體(goroutine)間的通信設施,和map類似,本質上是一個指針

ch := make(chan int)

4. 接口

對一組滿足某個契約的類型的抽象

//內部維持兩個指針
type Interface struct {
    data *void
    itab *Itab
}

 

四,結構體

go的結構體(struct)放棄了大量包括繼承在內的面向對象屬性,只保留了組合這個最基礎的屬性。go語言中結構體的使用方式和C語言相同:

//定義結構
type Rect struct {
    x, y float64
    width, height float64
}

//使用
func (r *Rect) Area() float64 {
    return r.width * r.height
}

結構初始化

在go中未顯示初始化的變量會被初始化成該類型的零值,而且沒有構造函數的概念,對象的創建由寫在外面獨立的全局的構造函數來完成:

func NewRect (x, y, width, height float64) *Rect {
    return &Rect(x, y, width, height)
}

Struct 類似於 java 中的類,可以在 struct 中定義成員變量。
要訪問成員變量,可以有兩種方式:
 1.通過 struct 變量.成員 變量來訪問。
2.通過 struct 指針.成員 變量來訪問。
不需要通過 getter, setter 來設置訪問權限。

 

參考資料:Go語言編程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章