【golog】我的go學與思11

方法和接口

正文

go 沒有類,但是能定義結構的成員函數:

package main

import (
	"fmt"
	"math"
)

type Vertex struct {
	X, Y float64
}

func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
	v := Vertex{3, 4}
	fmt.Println(v.Abs())
}

同時不想C++那樣有頭文件的概念,必須在一個文件內部定義和實現這個結構體的全部成員方法。

這種感覺就是像是一個結構體會有一個成員方法表,每當出現func (t Type) Foo()這種定義函數的時候直接在Type的方法表內部插入這個Foo函數。

go裏面也特別的區別了指針, 如果v.Foo()那麼不會改變v本身內部的值,而是對一個拷貝的值操作,但是定義是:func (t *Type) Foo()的時候,v.FOO的操作不是對拷貝的v操作而是v本身。

指針

var v Vertex
v.Scale(5)  // OK
p := &v
p.Scale(10) // OK

這裏我們看到了一個非常混淆的用法,在c++的寫法中,我們會明確的感知到代碼中值變量和指針變量:

Vertex v;
v.Scale(5)  // OK
Vertex* p = &v
p->Scale(10) // OK

看到了嗎?->.。go語言可能爲了簡潔是把->去掉了,但是我覺得這並不是一個很好的設計,因爲代碼閱讀的時候你會一眼看出來誰是值變量,誰是指針變量。

這裏go舉了例子:

//        當方法是外部方法的時候,
//    結構體的指針和值變量在代碼語法上是不一致的
var v Vertex
fmt.Println(AbsFunc(v))  // OK
fmt.Println(AbsFunc(&v)) // 編譯錯誤!

//        當方法是成員變量的時候,
//    結構體的指針和值變量在代碼語法上是一致的。
var v Vertex
fmt.Println(v.Abs()) // OK
p := &v
fmt.Println(p.Abs()) // OK

也就是說,內質爲成員方法是更加方便的。當然,調試起來有的時候忘記了爲啥變量改變就很麻煩了。

不要爲了方便而濫加成員變量,記住職責單一。

這裏我想知道,go語言是如何做const &的因爲有很多時候爲了避免開銷而是用引用,但是又想要避免值得改變。

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