• 一文了解 Go 方法


    前言

    在前面的 一文熟悉 Go 函数 文章中,介绍了 Go 函数的声明,函数的几种形式如匿名函数、闭包、基于函数的自定义类型和函数参数详解等,而本文将对方法进行介绍,方法的本质就是函数,介绍方法的同时也会顺带对比其与函数的不同之处。

    方法

    在 Go 中,我们可以为任何的数据类型定义方法(指针或接口除外),现在让我们看一看方法的声明和组成部分以及与函数有什么不同之处。

    type Person struct {
    	age int
    }
    
    func (p *Person) SetAge(age int) error {
    	if age < 0 {
    		return errors.New("年龄不能小于 0 ")
    	}
    	p.age = age
    	return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    上述代码定义了一个结构体 Person,此结构体包含一个 age 属性,一个 SetAge 方法,此方法只作用于 Person 结构体。我们可以看到,该方法包含六部分,分别为:

    1、关键字
    声明方法时,必须以 func 关键字开头,还记得函数的声明吗,也是以这个关键字开头。
    2、receiver 部分
    (p *Person) 这部分,在 Go 中称为 receiver 部分,里面的参数称为 receiver 参数,相比于函数,方法与其的声明区别就在于多了这一部分。
    3、方法名。
    Go 推荐使用驼峰命名的方式,和变量的命名规则一样,首字母大写的方法名可以在包外访问,小写的只能在包内访问。
    4、参数列表
    参数列表中声明了在方法体里所使用到的变量。参数列表位于方法名后面,用括号包裹着,多个参数使用逗号分隔开。
    5、返回值列表
    返回值为函数执行后的一个结果,上述代码只有一个返回值,如果有多个返回值,需要用括号包裹着,返回值之间用逗号分隔开。
    6、方法体
    大括号内就是方法体,存放着方法的具体实现。

    方法的调用

    通过 变量.方法名(参数) 的方式对方法进行调用。例如:

    import (
    	"errors"
    	"fmt"
    )
    
    type Person struct {
    	age int
    }
    
    func (p *Person) SetAge(age int) error {
    	if age < 0 {
    		return errors.New("年龄不能小于 0 ")
    	}
    	p.age = age
    	return nil
    }
    
    func main() {
    	person := Person{}
    	err := person.SetAge(18)
    	if err != nil {
    		return
    	}
    	fmt.Println(person.age) // 18
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    创建一个 person 变量,然后调用 SetAge 函数。

    Receiver 参数类型的选择

    在 Receiver 部分,我们可以绑定值类型,也可以绑定指针类型,这两种类型什么时候使用呢?

    如果方法体里不涉及到修改结构体变量的属性值,使用值类型

    type Person struct {
            age int
    }
    
    func (p Person) GetAge() int {
            return p.age
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    对于 GetAge 方法,作用是返回年龄,没有涉及到修改年龄的操作,因此 receiver 部分,选择 Person 类型就可以。
    如果方法体里有修改结构体变量的属性值的操作,使用指针类型

    
    type Person struct {
    	age int
    }
    
    func (p *Person) SetAge(age int) error {
    	if age < 0 {
    		return errors.New("年龄不能小于 0 ")
    	}
    	p.age = age
    	return nil
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    SetAge 涉及到对结构体属性值修改的操作,因此 receiver 部分使用指针类型,通过指针,可以对所指向地址的变量进行修改操作。

    方法的约束

    Go 对方法声明的位置是有约束的,我们不能跨越包去声明一个类型的方法,根据这个特点我们可以发现:

    不能为基本数据类型声明方法
    因为基本数据类型所定义的位置,是不在我们所编码的包里面的。

    不能跨越包为其他包的类型声明方法
    这个是 Go 的所规定的的。

    小结

    本文介绍了 Go 方法的声明方式、组成部分和其与函数的不同点,同时指出Receiver 参数类型在不同场景下的选择,最后介绍了 Go 对方法约束的体现。

  • 相关阅读:
    python+pytest接口自动化(3)-接口测试一般流程及方法
    Maven最新版的下载与安装教程(详细教程)
    JavaScript对象详解,js对象属性的添加
    让 GPT-4 来修复 Golang “数据竞争”问题 - 每天5分钟玩转 GPT 编程系列(6)
    银河麒麟Telnet远程登录
    [附源码]计算机毕业设计springboot天狗电子商城系统
    毫米波雷达人体感应器,智能感知静止存在,人体存在检测应用
    体验不尽,进化不止,看视频云技术六大创新
    如何正确实现一个自定义 Exception
    注塑车间是否需要导入MES系统?
  • 原文地址:https://blog.csdn.net/m0_73728511/article/details/133833527