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

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