Go並非一個相似於Java、C++,或PHP這樣內置面向對象語法的操做的語言,在Go裏面名義上是沒有類(class)這個概念的,可是這並不表明Go不能面向對象,畢竟面向對象只是一種設計思想!bash
爲何Go並不原生支持面向對象呢?這是一個問題app
接下來,我會從面向對象的三大特性封裝、繼承、多態這個幾個方面來說講Go是怎麼實現的OOP的。函數
閒話少說,在Go裏面可使用結構體模擬類:ui
type Goods struct {
name string
price int
}
複製代碼
在Go裏面有一個約定俗稱的規則,變量名、結構體名、結構體屬性成員名大寫表明是公開權限,能夠被其它包使用。相似於類的public屬性。若是小寫就相似於private屬性。spa
類裏面除了屬性以外,通常會有本身的方法,在Go裏面能夠這樣實現(這裏我採用的是Go modules結構):設計
package models
import "fmt"
type Goods struct {
Name string
Price int
}
func (g *Goods) GetName() string {
return g.Name
}
func (g *Goods) SetName(name string) {
g.Name = name
}
func (*Goods) String() {
fmt.Println("I am Goods")
}
複製代碼
其實就是在函數名前加一個類型聲明,若是你在方法裏面不須要使用類自己,則能夠省略參數標識。code
如何使用這個「類呢」?對象
package main
import (
"demo/models"
"fmt"
)
func main() {
goods := models.Goods{
"筆記本", 100,
}
fmt.Printf("Goods name is %s\n", goods.GetName())
goods.SetName("小米筆記本")
fmt.Printf("Goods name is %s\n", goods.GetName())
}
複製代碼
咱們能夠採用字面量賦值的方式初始化對象,雖然結構體並無構造函數這個東西,可是咱們能夠造個差很少的方式出來。繼承
新增這個方法:接口
func NewGoods(name string, price int) Goods {
g := Goods{
Name: name,
Price: price,
}
return g
}
複製代碼
而後咱們就能夠這樣使用:
var goods models.Goods
goods = models.NewGoods("筆記本", 1000)
複製代碼
其實區別卻是不大,封裝了一下,更加簡潔,雖然達不到構造函數自動調用的效果。
Go裏面並無extends這樣的語法,可是結構體的成員能夠是結構體,這其實是使用組合實現了繼承的效果。
package models
type Apple struct {
Goods //繼承了Goods
Color string
}
// 構造函數
func NewApple(name string, price int, color string) Apple {
apple := Apple{
Goods{name, price},
color,
}
return apple
}
複製代碼
main.go:
package main
import (
"demo/models"
"fmt"
)
func main() {
apple := models.NewApple("紅富士蘋果", 200, "red")
fmt.Printf("Apple name is %s", apple.GetName())
}
複製代碼
Apple可使用Goods的方法和屬性,使用組合的好處就是不存在多繼承的限制,在不少面向對象的語言裏面,只能單繼承。
雖然Go裏面也沒有implements這樣的關鍵字,可是在Go裏面可使用interface來實現多態效果,並且Go裏面的接口至關靈活。
定義接口:
package models
type Saleable interface {
Sell()
}
複製代碼
實現接口(Apple):
func (Apple) Sell() {
fmt.Println("我實現了saleable接口")
}
複製代碼
使用:
func main() {
apple := models.NewApple("紅富士蘋果", 200, "red")
var i models.Saleable
i = &apple
i.Sell()
}
---結果---
我實現了saleable接口
複製代碼
劃重點,在GO裏面只要一個結構體(struct)定義了一個接口(interface)裏面的全部方法,就意味着這個這個struct實現了這個接口,這是隱式的。可見,在Go裏面接口仍是挺好用的。