当前位置: 首页 > news >正文

Go进阶之理解方法本质

Go语言虽然不支持经典的面向对象的语法元素.比如继承 对象和类.Go语言也有方

法.和函数相比就是在声明形式上多了一个参数.Go称为receiver参数.receiver是参

数与类型之间的纽带.

方法声明格式:

func (receiver T/* T) MethodName(参数列表) (返回值列表){ //方法体 }

方法声明的T称为receiver的基类型.通过receiver.上述方法被绑定到类型T上.伪代码如下:

var t T t.methodName(参数列表) var pt *T = &t pt.methodName(参数列表)

    1.Go方法特点:

    1).方法名的首字母是否大写决定了该方法是不是导出方法.

    2).方法定义要与类型定义放在同一个包内.由此可以知道不能为原生类型(如int

    float64 map等)添加方法.只能为自定义类型定义方法.示例如下.

    type MyInt int64 func (i MyInt) String() string { return "自定义类型的方法" }

    同理可以得出不能跨域Go包为其他包内的自定义类型定义方法.

    3).每个方法只能有一个receiver参数.不支持多receiver参数列或变长receiver参

    数.一个方法只能绑定一个基类型.Go语言不支持同时绑定多个类型的方法.

    4).receiver参数的基类型本身不能是指针类型或者接口类型.示例如下.

    2.方法的本质:

    Go语言没有类.方法与类别通过reveiver联系到一起,可以为任何非内置原生类型定

    义方法.示例如下:

    type T struct { a int } func (t T) get() int { return t.a } func (t *T) set(a int) { t.a = a }

    receiver其实是作为第一个参数传入方法列表中.上述的方法可以等价转换为下面的

    函数,代码如下:

    func Get(t T) int { return t.a } func Set(t *T, a int) { t.a = a }

    这种转换后的函数就是方法的原型.只不过在Go语言中.这种等价转换是由Go编译器

    在编译和生成代码时自动完成的.Go语言规范中提供了一个新的概念.可以更充分理解

    等价转换.

    Go方法一般使用方式:

    func Test() { var t T t.get() t.set(1000) }

    等价替换:

    func ChangeTest() { var t T T.get(t) (*T).set(&t, 1000) }

    这种直接以类型名T调用方法的表达式被称为方法表达式.类型T只能调用T的方法集

    合(Method Set)中的方法.同理.*T只能调用*T的方法集合中的方法.这种通过方法表

    达式进行调用的方式与我们之前所做的方法到函数的等价转换如出一辙.这就是Go方

    法的本质.一个方法所绑定类型实例为第一个参数的普通函数.

    Go方法本身就是一个普通函数.我们甚至可以把它作为右值赋值给函数类型的变量.

    func Test() { var t T f1 := (*T).set f2 := T.get f1(&t,1) fmt.Println(f2(t)) }

    3.选择正确的reveiver类型:

    方法和函数的等价变换公式:

    func(t T) M1()<=> M1(t T) func(t *T) M2()<=> M2(t *T)

    M1方法的receiver参数类型为T.M2方法的receiver参数类型为*T.

    1).receiver类型为T时:

    选择以T作为receiver参数类型时.T的M1方法等价于M1(t T).Go函数的参数采用的

    是值复制传递.也就是说M1函数体中的t是T类型的一个副本.这样在M1函数实现中对

    参数t做任何修改都只会影响副本.不会影响到原T类型.

    2).receiver类型为*T时:

    选择以*T作为receiver参数类型时.T的M2方法等价为M2(t *T).我们传递给M2函

    数的t是T类型实例的地址.这样M2函数体中对参数t做的任何修改都会反应到原T类

    型实例上.

    示例如下:

    func main() { //t.a=0 var t T fmt.Println(t.a) t.M1() fmt.Println(t.a) t.M2() fmt.Println(t.a) } type T struct { a int } func (t T) M1() { t.a = 10 } func (t *T) M2() { t.a = 11 }

    执行结果:

    疑惑:是不是T类型实例只能调用receiver为T的类型方法.不能调用receiver为*T类

    型的方法呢.答案是否定.无论T类型实例还是*T类型实例.都既可以调用receiver为T

    类型的方法.也可以调用receiver为*T类型的方法.示例如下:

    func main() { var t T var pt = &T{} t.M1() t.M2() pt.M1() pt.M2() }

    可以看到上述都可以进行互相调用.实际上这都是Go语法糖.Go编译器在编译和生成

    代码时为我们做了自动转换.

    总结:

    如果要对类型实例进行修改.可以为receiver选择*T类型.

    如果没有对类型实例修改的需求.可以为receiver选择T类型或*T类型均可.如果类型

    的size过大的话.选择指针会更好一些.

    微笑着孤言寡语.

    如果大家喜欢我的分享的话.可以关注我的微信公众号

    念何架构之路

    http://www.jsqmd.com/news/305042/

    相关文章:

  • IntelliJ IDEA 全局搜索完全指南:从高效使用到快捷键失效排查
  • 费雪的研发投入分析:创新如何驱动企业长期增长
  • SMB挂载与iSCSI挂载飞牛存储:你该选择哪一种连接方式?
  • 重命名你的电脑,给它发个“工牌”吧!
  • DevOps是什么?
  • 例说FPGA:可直接用于工程项目的第一手经验【1.1】
  • [高质量代码分享] JavaScript 空值判断(工具)函数
  • 强烈安利专科生必用9款一键生成论文工具测评
  • 吐血推荐9个AI论文软件,专科生搞定毕业论文!
  • 影悦电影推荐系统的设计与实现开题报告
  • 小额消费贷款产品特征抽取与推荐分析平台的设计与实现开题报告
  • YOLO26改进 - 注意力机制 | 多扩张通道细化器MDCR 通过通道划分与异构扩张卷积提升小目标定位能力
  • YOLO26改进策略【Backbone/主干网络】| ICLR-2023 替换骨干网络为:RevCol 一种新型神经网络设计范式
  • 闲置京东超市卡变现认准京顺回收
  • 微服务架构设计大比拼:独立数据库 VS 集中式DAO,谁才是真香定律?
  • Span和mspan的关系在go中是怎么定义的
  • 提示工程架构师必看:智能法律助手中的提示工程实战指南
  • YOLO26最新创新改进系列:Involution新卷积网络算子融合于YOLO网络,从经典的图像滤波方法中汲取灵感,更大的空间范围中总结上下文信息,有效涨点!
  • YOLO26最新创新改进系列:融合简单但功能强大的主干网络-BoTNet模块,获得CNN+自然语言处理技术的优势,有效提升检测效果!
  • 星图 ai.csdn.net CSDN 的「大模型工坊」只能“一键微调”官方底座,不支持真正的预训练/RLHF,训练完可以私有化部署,但可控度、底座选择、数据安全都弱于公有云
  • CSS - code
  • YOLO26改进策略【Backbone/主干网络】| 替换骨干为PoolFormer,基于平均池化的Token混合器,通过聚合局部邻域特征实现信息交互
  • YOLO26改进策略【Backbone/主干网络】| CVPR 2024 替换骨干为InceptionNeXt,将大核深度卷积分解为四个并行分支,平衡速度与精度
  • YOLO26改进策略【Backbone/主干网络】| 替换骨干网络为2023-CVPR LSKNet (附网络详解和完整配置步骤)
  • YOLO26改进策略【Backbone/主干网络】| 替换骨干网络为2023-CVPR ConvNeXt V2 (附网络详解和完整配置步骤)
  • YOLO26改进策略【Backbone/主干网络】| 替换骨干网络为CVPR-2024 PKINet 获取多尺度纹理特征,适应尺度变化大的目标
  • YOLO26改进策略【Backbone/主干网络】| CVPR 2024替换骨干网络为 UniRepLKNet,解决大核 ConvNets 难题
  • 提示工程架构师的“数据思维”:用数字提升提示吸引力
  • YOLO26改进策略【Backbone/主干网络】| CVPR 2024 替换骨干网络为 RMT,增强空间信息的感知能力
  • 02.