Go語言學習Part4-1:方法和接口

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)
}

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