Go語言- 面向 “物件” 與java的不同

語言: CN / TW / HK

go中沒有其他語言中的繼承

go認為有interface足以,不用例如java中的extends 等關鍵字 來表達所謂子類和父類的關係。這對一些初學者來說 可能會比較迷惑。

舉例說明:

先定義一個person 代表人 ``` type Person struct { Name string Age int }

func (person Person) print(){ fmt.Println("name:",person.Name," age: ",person.Age) } ```

我們可以基於此 定義一個學生

可以看出來 我們是把 Person 作為一個指標的變數 封裝到一個Student中

``` type Student struct { Person *Person //班級 Class string

}

func (stu Student) print(){ fmt.Println("name:",stu.Person.Name," age: ",stu.Person.Age," class:",stu.Class) } ``` 最後看下是如何呼叫的

``` func main() { person:=Person{"wuyue",18} person.print()

stu:=Student{&person,"三班"} stu.print() } ```

使用 內嵌 語法糖

``` type NewStudent struct { *Person //內嵌 語法糖 Class string

} ```

```

func (stu NewStudent) print(){ fmt.Println("name:",stu.Name," age: ",stu.Age," class:",stu.Class) } ```

使用了內嵌這種語法糖以後 可以看出來是可以省略一些程式碼的。 不用stu.person 這種寫法了。

“alias“ 別名 擴充套件已有的型別

在go語言中 type還可以充當別的語言中 別名的 作用

例如 我在這裡完全可以 定義一個 實質為切片 但是功能上和佇列是一個性質的 Queue 結構體

``` type Queue []int

func (q Queue) Push(v int) { q = append(*q, v) } ```

go是沒有建構函式的,一般會用工廠函式來做類似建構函式的操作

func createPersonByName(name string) *Person{ return &Person{Name: name} }

go的struct 遵循了嚴格的值傳遞

這一點和java有本質的不同。 從java轉過來的同學 一開始可能會很不習慣

定義了2個方法

func ChangeAge(person Person,age int){ person.Age=age } func ChangeAge2(person *Person,age int){ person.Age=age }

看下實際的呼叫

func main() { person:=Person{"wuyue",18} person.print() ChangeAge(person,100) person.print() ChangeAge2(&person,100) person.print() }

看下結果:

image.png

可以看出來 函式引數不是指標的方法,修改struct的值 是完全無效的

實際上對於go語言來說,操作struct時 更推薦用指標作為引數,因為效能更好,否則會觸發一次 拷貝的操作。

其餘一些重要的知識點

go檔案的包名可以和資料夾名稱不一樣,這和java不同

同一個資料夾下,所有go檔案的 包名都必須一致

首字母大寫 其他包才能引用到 才是public的

要理解好函式的recevier這個概念,go中的receiver與kotlin語言的receiver 十分接近 // 括號內 代表這個函式的 receiver 代表只有這個 struct 才可以呼叫 // 這和其他語言把方法定義在所謂class裡面 是不同的 func (node TreeNode) print(){ fmt.Println(node.value) }