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