Golang作爲一種“更好的C語言“,提供了面向對象編程思想的支持。
這一篇是上一篇的補充,主要闡述了go語言面向對象的一些特性,值傳遞和指針傳遞在go語言的運用,並補充了一些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語言編程