代码改变世界

golang receiver of method方法接收者

2022-05-04 12:45  youxin  阅读(131)  评论(0编辑  收藏  举报

什么是method(方法)?method是函数的另外一种形态,隶属于某个类型的方法。

method的语法:

func (r Receiver) funcName (parameters) (result)

receiver可以看作是method的第一个参数,method并且支持继承和重写。

  • Go中虽没有class,但依旧有method
  • 通过显示说明receiver来实现与某个类型的结合
  • 只能为同一个包中的类型定义方法
  • receiver可以是类型的值或者指针
  • 不存在方法重载
  • 可以使用值或指针来调用方法,编译器会自动完成转换
  • 从某种意义上来说,方法是函数的语法糖,因为receiver其实就是方法所接收的第一个参数(Method Value vs. Method Expression)
  • 如果外部结构和嵌入结构存在同名方法,则优先调用外部结构的方法
  • 类型别名不会拥有底层类型所附带的方法
  • 方法可以调用结构中的非公开字段

 

⽅法总是绑定对象实例,并隐式将实例作为第⼀实参 (receiver)。

• 方法有一个值类型和指针类型的接受者时,都可以直接调用,内部会
自动进行语法的转换。

package main

import (
    "fmt"
)

type A struct {
    Name string
}

type B struct {
    Name string
}

func main() {
    //Receiver 可以是类型的值或者指针
    a := A{}
    a.Print()
    fmt.Println(a.Name) //打印为修改后的值

    b := B{}
    b.Print()
    fmt.Println(b.Name) //打印为空
}

//引用类型,指针的拷贝
func (a *A) Print() {
    a.Name = "AA"
    fmt.Println("A...")
}

//值类型,值得拷贝
func (b B) Print() {
    b.Name = "BB"
    fmt.Println("B...")
}
提阶,方法也支持提阶

 

    emp1 := Employee{
        name:     "张三",
        salary:   6000,
        currency: "$",
        age:      18,
        Address:  Address{"山东", "济南"},
    }
    //提阶
    emp1.fullAddress()         //山东 济南,提阶相当于直接访问Address里的
    emp1.Address.fullAddress() //山东 济南
非结构类型的方法

非结构体类型也可以定义方法,不过这里需要注意一点。为了定义某个类型的方法,接收者类型的定义与方法的定义必须在同一个包中。

因为必须在一个包中而int则在main包中我们没法去定义这个里为了简单直观,给int声明了别名

 
//非结构体方法扩展
type myInt int

func (a myInt) add(b myInt) myInt {
    return a + b
}
func main() {
    //调用扩展的方法
    num1 := myInt(5)
    num2 := myInt(10)
    sum := num1.add(num2)
    fmt.Println("Sum is", sum)

}
package main

import (
    "fmt"
    "math"
)

//Employee 需要添加注释或者改成非导出变量(首字母小写)
type Employee struct {
    name     string
    currency string
    salary   int
    age      int
    Address
}

//Address 代码规范
type Address struct {
    city  string
    state string
}

//Rectangle 代码规范
type Rectangle struct {
    width  float32
    height float32
}

//Circle 代码规范
type Circle struct {
    radius float32
}

//Employee 的方法
func (e Employee) displaySalary() {
    fmt.Println(e)
}
func (e Employee) changeName(newName string) {
    e.name = newName
}
func (e *Employee) changeAge(newAge int) {
    e.age = newAge
}

//Address 的方法
func (add Address) fullAddress() {
    fmt.Println(add.city, add.state)
}

//Rectangle 的方法计算面积
func (r Rectangle) getArea() float32 {
    return r.width * r.height
}

//Circle  的方法
func (c Circle) getArea() float32 {
    return math.Pi * c.radius * c.radius
}

//非结构体方法扩展
type myInt int

func (a myInt) add(b myInt) myInt {
    return a + b
}
func main() {
    //调用方法
    emp1 := Employee{
        name:     "张三",
        salary:   6000,
        currency: "$",
        age:      18,
        Address:  Address{"山东", "济南"},
    }
    emp1.displaySalary()

    fmt.Println("Before call changeName ", emp1.name)
    //修改名字,未发生变化因为是值传递
    emp1.changeName("zhangsan")
    fmt.Println("After call changeName ", emp1.name) //After call changeName  张三

    fmt.Println("Before change age", emp1.age)
    //利用指针来修改年龄
    emp1.changeAge(50)
    fmt.Println("After change age", emp1.age) //After change age 50

    //提阶
    emp1.fullAddress()         //山东 济南,提阶相当于直接访问Address里的
    emp1.Address.fullAddress() //山东 济南

    //计算面积
    re := Rectangle{20, 30}
    c := Circle{40}
    //两个类型调用同名方法
    fmt.Println(re.getArea())
    fmt.Println(c.getArea())

    //调用扩展的方法
    num1 := myInt(5)
    num2 := myInt(10)
    sum := num1.add(num2)
    fmt.Println("Sum is", sum)

}