對我來講,最吸引個人不是Go擁有的特徵,而是那些被故意遺漏的特徵。 —— txxxxdgolang
爲何你要創造一種從理論上來講,並不使人興奮的語言?
由於它很是有用。 —— Rob Pikejson
要探討Go語言中的對象,咱們先搞清楚一個問題:數組
從語法上來講,函數
對象是一種抽象的數據類型,擁有狀態(數據)和行爲(代碼)。 —— Steve Franciaui
在Go語言中,咱們這樣聲明一個類型:code
type Rect struct { width int height int }
func (r *Rect) Area() int { return r.width * r.height }
func main() { r := Rect{width: 10, height: 5} fmt.Println("area: ", r.Area()) }
咱們不光能夠聲明結構體類型,咱們能夠聲明任何類型。好比一個切片:對象
type Rects []*Rect
func (rs Rects) Area() int { var a int for _, r := range rs { a += r.Area() } return a }
func main() { r := &Rect{width: 10, height: 5} x := &Rect{width: 7, height: 10} rs := Rects{r, x} fmt.Println("r's area: ", r.Area()) fmt.Println("x's area: ", x.Area()) fmt.Println("total area: ", rs.Area()) }
https://play.golang.org/p/G1OWXPGvc3繼承
咱們甚至能夠聲明一個函數類型接口
type Foo func() int
func (f Foo) Add(x int) int { return f() + x }
func main() { var x Foo x = func() int { return 1 } fmt.Println(x()) fmt.Println(x.Add(3)) }
https://play.golang.org/p/YGrdCG3SlIip
經過上邊的例子,這樣看來,其實
那麼咱們來看看
若是一種語言包含對象的基本功能:標識、屬性和特性,則一般認爲它是基於對象的。
若是一種語言是基於對象的,而且具備多態性和繼承性,那麼它被認爲是面向對象的。 —— Wikipedia
第一條,咱們在上邊的例子看到了,go中的type declaration其實知足了Go語言是基於對象的。那麼,
咱們來看看關於第二條,繼承性和多態性
繼承把「知識」向下傳遞,組合把「知識」向上拉昇 —— Steve Francia
type Person struct { Name string Address } type Address struct { Number string Street string City string State string Zip string }
func (a *Address) String() string { return a.Number + " " + a.Street + "\n" + a.City + ", " + a.State + " " + a.Zip + "\n" }
func main() { p := Person{ Name: "Steve", Address: Address{ Number: "13", Street: "Main", City: "Gotham", State: "NY", Zip: "01313", }, } }
func main() { p := Person{ Name: "Steve", Address: Address{ Number: "13", Street: "Main", City: "Gotham", State: "NY", Zip: "01313", }, } fmt.Println(p.String()) }
https://play.golang.org/p/9beVY9jNlW
func (a *Address) String() string { return a.Number + " " + a.Street + "\n" + a.City + ", " + a.State + " " + a.Zip + "\n" } func (p *Person) String() string { return p.Name + "\n" + p.Address.String() }
外部結構的方法和內部結構的方法都是可見的
func main() { p := Person{ Name: "Steve", Address: Address{ Number: "13", Street: "Main", City: "Gotham", State: "NY", Zip: "01313", }, } fmt.Println(p.String()) fmt.Println(p.Address.String()) }
https://play.golang.org/p/Aui0nGa5Xi
func isValidAddress(a Address) bool { return a.Street != "" } func main() { p := Person{ Name: "Steve", Address: Address{ Number: "13", Street: "Main", City: "Gotham", State: "NY", Zip: "01313", }, } // 這裏不能用 p (Person類型) 做爲 Address類型的IsValidAddress參數 // cannot use p (type Person) as type Address in argument to isValidAddress fmt.Println(isValidAddress(p)) fmt.Println(isValidAddress(p.Address)) }
https://play.golang.org/p/KYjXZxNBcQ
爲不一樣類型的實體提供單一接口
一般經過泛型、重載和/或子類型實現
Go語言採用了鴨式辯型,和JavaScript相似。鴨式辯型的思想是,只要一個動物走起路來像鴨子,叫起來像鴨子,那麼就認爲它是一隻鴨子。 也就是說,只要一個對象提供了和某個接口一樣(在Go中就是相同簽名)的方法,那麼這個對象就能夠當作這個接口來用。並不須要像Java中同樣顯式的實現(implements)這個接口。
type Shaper interface{ Area() int }
func Describe(s Shaper) { fmt.Println("Area is: ", s.Area()) }
func main() { r := &Rect{width: 10, height: 5} x := &Rect{width: 7, height: 10} rs := &Rects{r, x} Describe(r) Describe(x) Describe(rs) }
https://play.golang.org/p/WL77LihUwi
「若是你能夠從新作一次Java,你會改變什麼?」
「我會去掉類class,」 他回答道。
在笑聲消失後,他解釋道,真正的問題不是類class自己,而是「實現」的繼承(類之間extends的關係)。接口的繼承(implements的關係)是更可取的方式。
只要有可能,你就應該儘量避免「實現」的繼承。
—— James Gosling(Java之父)
這也就是上邊所說的鴨式辯型
type Reader interface { Read(p []byte) (n int, err error) }
type Writer interface { Write(p []byte) (n int, err error) }
func MarshalGzippedJSON(r io.Reader, v interface{}) error { raw, err := gzip.NewReader(r) if err != nil { return err } return json.NewDecoder(raw).Decode(&v) }
func main() { f, err := os.Open("myfile.json.gz") if err != nil { log.Fatalln(err) } defer f.Close() m := make(map[string]interface{}) MarshalGzippedJSON(f, &m) }
func main() { resp, err := http.Get("...") if err != nil { log.Fatalln(err) } defer resp.Body.Close() out, err := os.Create("filename.ext") if err != nil { log.Fatalln(err) } defer out.Close() io.Copy(out, resp.Body) // out io.Writer, resp.Body io.Reader }
簡單比複雜更難:你必須努力使你的思惟清晰,使之簡單。但最終仍是值得的,由於一旦你到了那裏,你就能夠移山。 —— Steve Jobs