• 结构体——方法和接收器,为任意类型添加方法


    1、方法和接收器

    在Go语言中,结构体就像是类的一种简化形式,那么类的方法在哪里呢?在Go语言中有一个概念,它和方法有着同样的名字,并且大体上意思相同,Go 方法是作用在接收器(receiver)上的一个函数,接收器是某种类型的变量,因此方法是一种特殊类型的函数。

    接收器类型可以是(几乎)任何类型,不仅仅是结构体类型,任何类型都可以有方法,甚至可以是函数类型,可以是 int、bool、string 或数组的别名类型,但是接收器不能是一个接口类型,因为接口是一个抽象定义,而方法却是具体实现,如果这样做了就会引发一个编译错误invalid receiver type…。

    接收器也不能是一个指针类型,但是它可以是任何其他允许类型的指针,一个类型加上它的方法等价于面向对象中的一个类,一个重要的区别是,在Go语言中,类型的代码和绑定在它上面的方法的代码可以不放置在一起,它们可以存在不同的源文件中,唯一的要求是它们必须是同一个包的。

    类型 T(或 T)上的所有方法的集合叫做类型 T(或 T)的方法集。

    因为方法是函数,所以同样的,不允许方法重载,即对于一个类型只能有一个给定名称的方法,但是如果基于接收器类型,是有重载的:具有同样名字的方法可以在 2 个或多个不同的接收器类型上存在,比如在同一个包里这么做是允许的

    在面向对象的语言中,类拥有的方法一般被理解为类可以做的事情。在Go语言中“方法”的概念与其他语言一致,只是Go语言建立的“接收器”强调方法的作用对象是接收器,也就是类实例,而函数没有作用对象。

    接收器的格式如下:

    func (接收器变量 接收器类型) 方法名(参数列表) (返回参数) {
        函数体
    }

    对各部分的说明:

    • 接收器变量:接收器中的参数变量名在命名时,官方建议使用接收器类型名的第一个小写字母,而不是 self、this 之类的命名。例如,Socket 类型的接收器变量应该命名为 s,Connector 类型的接收器变量应该命名为 c 等。
    • 接收器类型:接收器类型和参数类似,可以是指针类型和非指针类型。
    • 方法名、参数列表、返回参数:格式与函数定义一致。

    接收器根据接收器的类型可以分为指针接收器、非指针接收器,两种接收器在使用时会产生不同的效果,根据效果的不同,两种接收器会被用于不同性能和功能要求的代码中。

    1)指针类型的接收器

    指针类型的接收器由一个结构体的指针组成,更接近于面向对象中的 this 或者 self。
    由于指针的特性,调用方法时,修改接收器指针的任意成员变量,在方法结束后,修改都是有效的。

    示例:

    package main
    import "fmt"
    
    type Property struct {
    	value int
    }
    
    func (p *Property) SetValue(v int) {
    	p.value = v
    }
    
    func (p *Property) Value() int {
    	return p.value
    }
    func main() {
    	p := new(Property)
    	p.SetValue(100)
    	fmt.Println(p.Value())
    }
    

      

    2)非指针类型的接收器

    当方法作用于非指针接收器时,Go语言会在代码运行时将接收器的值复制一份,在非指针接收器的方法中可以获取接收器的成员值,但修改后无效。

    示例:

    package main
    import (
    	"fmt"
    )
    
    type Point struct {
    	X int
    	Y int
    }
    
    func (p Point) Add(other Point) Point {
    	return Point{p.X + other.X, p.Y + other.Y}
    }
    func main() {
    	p1 := Point{1, 1}
    	p2 := Point{2, 2}
    	result := p1.Add(p2)
    	fmt.Println(result)
    }
    

      

    3)指针和非指针接收器的使用

    在计算机中,小对象由于值复制时的速度较快,所以适合使用非指针接收器,大对象因为复制性能较低,适合使用指针接收器,在接收器和参数间传递时不进行复制,只是传递指针。

    2、为任意类型添加方法

    Go语言可以对任何类型添加方法,给一种类型添加方法就像给结构体添加方法一样,因为结构体也是一种类型。

    示例:

    package main
    import (
    	"fmt"
    )
    // 将int定义为MyInt类型
    type MyInt int
    
    func (m MyInt) IsZero() bool {
    	return m == 0
    }
    
    func (m MyInt) Add(other int) int {
    	return other + int(m)
    }
    func main() {
    	var b MyInt
    	fmt.Println(b.IsZero())
    	b = 1
    	fmt.Println(b.Add(2))
    }
    

      

  • 相关阅读:
    Multiple markers at this line
    用递归和位移进行枚举子集合
    Android开发如何双击返回键退出程序
    Android ImageView设置图片原理(下)
    北大OJ百练——2721:忽略大小写比较字符串大小
    场景示例 Nginx 访问日志
    2 插件管理
    第一章 入门示例
    zabbix 通过gateway 获取远程主机的JMX信息
    zabbix 通过gateway 获取远程主机的JMX信息
  • 原文地址:https://www.cnblogs.com/ACGame/p/11922546.html
Copyright © 2020-2023  润新知