美文网首页
go 接收器

go 接收器

作者: hijiang | 来源:发表于2019-05-25 10:34 被阅读0次

go的函数调用包括两种:1、有接收器的,我们称之为方法;2、无接收器的,我们称之为函数;
方法又包含两种:
1、指针方法:指针做为接收器;
2、值方法:值做为接收器;

  • 指针方法可以改变对象的field,相当于C里的指针;
  • 值方法不会改变对象的field
  • 一个对象包含的所有值方法称为值方法集;
  • 一个对象包含的所有指针方法,称为指针方法集;

go的参数传递总是值传递,只不过如果传递的是指针,那么可以改变指针所指对象;

关于接收器有两个非常重要的规则,必须要牢记,对于设计接口非常有必要知道:

  • 值只包含值方法集,不包含指针方法集;
  • 指针包含值方法集,也包含值方法集(全部都有就对了)

所以有时我们需要将一个对象赋值给接口时,如果传值,但是值只实现了接口的值方法,而没实现指针方法,就会报运行时错误;而如果传递指针,肯定没有问题;

下面是一些测试的代码,虽然简单,但是可以说明问题:

package main

import (
    "fmt"
    "reflect"
)

type Animal interface {
    Walk(step int)
    Walk1(step int)
}

type People struct {
    Name     string
    CurrStep int
}

func (c People) PeInfo() {
    fmt.Println("people name:", c.Name, " currstep:", c.CurrStep)
}

func (c *People) SetName(name string) {
    c.Name = name
    fmt.Println("people new name:", name)
}

func (c People) Walk(step int) {
    c.PeInfo()
    c.CurrStep += step
    fmt.Println(" walk ", step)
}

func (c *People) Walk1(step int) {

}

func PrintMethodSet(i interface{}) {
    rt := reflect.TypeOf(i)
    fmt.Println("type is ", rt)
    for i, n := 0, rt.NumMethod(); i < n; i++ {
        fmt.Println("\tit has method:", rt.Method(i).Name)
    }
}

func LetWalk(a Animal, s int) {
    a.Walk(s)
}

func LetWalk1(p People, s int) {
    p.Walk(s)
}

func main() {
    var p = People{Name: "jiangbaolin"}
    PrintMethodSet(p)
    //下面两句等效
    p.PeInfo()
    /*
        指针调用值方法,指针包含所有方法集,指针调用值方法时,会通过指针创建值副本,然后再调用值方法;
        效果等同于:
        q := *(&p)
        q.PeInfo()
    */
    (&p).PeInfo()
    People.PeInfo(p)
    // People.PeInfo(&p) //语句错误,这里需要显示传递指针
    //下面三句等效
    p.SetName("xiaoming") //p是值类型,不包含指针方法,但是go 隐式调用了(&p).SetName("jiang")语法糖,所以可以调用
    (&p).SetName("xiaojiang")
    (*People).SetName(&p, "liu")

    // var q Animal = p //p是值,不包含 Walk1指针方法,但Animal需要实现Walk1方法,所以报错
    // PrintMethodSet(q)
    var m Animal = &p //指针包含所有方法集,所以可以使用
    PrintMethodSet(m)
    //不会改变p
    LetWalk(&p, 10) //等效于LetWalk(*(&p), 10)
    p.PeInfo()
    // LetWalk(p, 10) //编译错误,p没法转为Animal
    // p.PeInfo()
    // var i interface{} = p //执行时报错,p没有实现Walk1
    // i.(Animal).Walk(10)

    var j interface{} = &p //执行时报错,p没有实现Walk1
    j.(Animal).Walk(10)    //正确

    LetWalk1(p, 10)
    p.PeInfo()
    // LetWalk1(&p, 10)  //语法错误,不接收值接收器
    p.PeInfo()
}

相关文章

  • go 接收器

    go的函数调用包括两种:1、有接收器的,我们称之为方法;2、无接收器的,我们称之为函数;方法又包含两种:1、指针方...

  • Go接口实例

    Go支持在struct类型上定义的方法。area方法有一个* rect类型的接收器。可以为指针或值接收器类型定义方...

  • Go接口实例

    Go支持在struct类型上定义的方法。area方法有一个* rect类型的接收器。可以为指针或值接收器类型定义方...

  • Go语言之Interface(二)

    使用指针接收器和值接收器实现接口 实现多个接口 接口嵌套 在Go语言中没有继承的概念,但是通过组合可以实现继承的效...

  • Go Method

    Go语言同时支持函数和方法,方法是包含接收器的函数,接收器可以是命名类型或结构体类型的值或指针。为特定类型定义的方...

  • 详解Go 语言中的方法

    go 方法 定义 方法是具有特殊接收器参数的函数,即在 func 和方法名之间方法接收者。 func(sStude...

  • 罗技M590蓝牙连接

    1)首次连接 接收器没有连接到电脑上。 鼠标和键盘装上电池。 把接收器插上电脑。 鼠标与接收器对码(接收器一定要接...

  • Go 接口与指针接收器的问题

    提示错误 因为我只实现*person的接口,而没实现person的接口,所以在sayHeight时,需要将p改为&p。

  • Go语言如何选择方法接收器的类型

    Go语言中的方法 方法用于给指定数据类型(非内置数据类型)添加新的行为,方法实质上也是函数,与函数不同的是,每个方...

  • 创建自定义的事件接收器-Semantic Logging

    创建自定义的事件接收器 Semantic Logging Application Block提供了大量的事件接收器...

网友评论

      本文标题:go 接收器

      本文链接:https://www.haomeiwen.com/subject/dkdazqtx.html