https://tour.go-zh.org/methods/1
(熱)愛是力量之泉!!
struct定義方法
- Go木有類,但是可以爲struct定義方法
- func (v structName) methodName
方法寫成函數
//case 1
package main
import (
"fmt"
"math"
)
type Pos struct {
x float64
y float64
}
func (temp Pos) abs() float64{
return math.Sqrt(temp.x*temp.x+temp.y*temp.y)
}
func sum(temp Pos) float64 {
return temp.x+temp.y
}
func main() {
var v Pos
v = Pos{3, 4}
fmt.Println(sum(v))
}
非結構體的數據類型增加方法【666】
- 類型定義和方法說明必須在一個包裏面
//case 2
package main
import (
"fmt"
"math"
)
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
func main() {
f := MyFloat(-math.Sqrt2) // 根號2的值
fmt.Println(f.Abs())
}
指針接收者和值接收者區別
- 指針接收者的方法可以修改接收者指向的值
- 值接收者,會對原始 Vertex 值的副本進行操作
//case 3
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 (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func (v Vertex) JustScaleWhile(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex{3, 4}
v.JustScaleWhile(10)
fmt.Println(v.Abs())
v.Scale(10)
fmt.Println(v.Abs())
}
指針與函數
- 帶指針參數的函數必須接受一個指針;接受一個值作爲參數的函數必須接受一個指定類型的值(函數參數是值,必須傳值;是指針,必須傳指針)
接收者不同的函數
- 指針爲接收者的方法被調用時,接收者既能爲值又能爲指針, 見case4
- 可以修改接收者指向的值
- 避免每次調用複製該值
- 以值爲接收者的方法被調用時,接收者既能爲值又能爲指針,見case5
- 接收者爲指針的時候,值並沒有被修改
//case 4
var v Vertex
v.Scale(5) // OK
p := &v
p.Scale(10) // OK
//case5
var v Vertex
fmt.Println(v.Abs()) // OK
p := &v
fmt.Println(p.Abs()) // OK
接口
- 定義:一組方法簽名定義的集合
- 對象調用接口的函數會執行
- 類型通過實現一個接口的所有方法來實現該接口
- 接口值可以作爲函數的參數或返回值
- 接口內的具體值爲nil,方法依然會被nil接收者調用
//case 5
package main
import (
"fmt"
)
type getinfo interface {
gettypeinfo() string
M()
}
type Myint int
func (x Myint) gettypeinfo() string {
return "int type"
}
func (x Myint) M() {
fmt.Println(x)
}
type MyintStruct struct {
element int
}
func (x *MyintStruct) gettypeinfo() string {
return "int struct type"
}
func (x *MyintStruct) M() {
if x == nil {
fmt.Println("<nil>")
return;
}
fmt.Println(x.element)
}
func describe(t getinfo) {
fmt.Printf("(%v, %T)\n",t, t)
}
func main() {
var b Myint
info := b
info.M()
fmt.Println(info.gettypeinfo())
describe(info)
info = Myint(2)
describe(info) //值作爲函數的參數
var info1 getinfo
var a *MyintStruct
info1 = a
describe(info1)
info1.M()
}
- nil接口值調用方法會運行錯誤,因爲接口沒有說明具體調用哪個實現的方法
- 零個方法的接口值被稱之爲空接口,可以接受各種未知類型 case6
//case 6
package main
import "fmt"
func main() {
var i interface{}
describe(i)
i = 42
describe(i)
i = "hello"
describe(i)
}
func describe(i interface{}) {
fmt.Printf("(%v, %T)\n", i, i)
}