Golang——方法

一. 方法定义

        Golang方法总是绑定对象的实例,并隐式将实例作为第一实参。

  • 只能为当前包内命名类型定义方法
  • 参数receiver可以任意命名。如方法中未曾使用,可省略参数名
  • 参数receiver类型可以是T或*T。基类型T不能是接口或指针类型(即多级指针)
  • 不支持方法重载,receiver只是参数前面的组成部分
  • 可用实例value或pointer调用全部方法,编译器自动转换

        一个方法就是一个包含接收者(receiver)的函数,接收者(receiver)可以是命名类型或者结构体类型的一个值或者是一个指针。

        所有给定类型的方法属于该类型的方法集。

        1.1 方法定义

func (reveicer type) methodName(参数列表)(返回值列表){}

//参数和返回值可以省略
package main

type test struct{}

// 接收者为值类型,无参,无返回值
func (t test) method0() {}

// 接收者为值类型,单参,无返回值
func (t test) method1(x int) {}

// 接收者为值类型,无参,单返回值
func (t test) method2() (res int) { return }

// 接收者为值类型,多参,无返回值
func (t test) method3(x, y int) {}

// 接收者为值类型,无参,多返回值
func (t test) method4() (res1, res2 int) { return }

// 接收者为值类型,多参,多返回值
func (t test) method5(x, y int) (res1, res2 int) { return }

// 接收者为指针类型,无参,无返回值
func (t *test) method6() {}

// 接收者为指针类型,单参,无返回值
func (t *test) method7(x int) {}

// 接收者为指针类型,无参,单返回值
func (t *test) method8() (res int) { return }

// 接收者为指针类型,多参,无返回值
func (t *test) method9(x, y int) {}

// 接收者为指针类型,无参,多返回值
func (t *test) method10() (res1, res2 int) { return }

// 接收者为指针类型,多参,多返回值
func (t *test) method11(x, y int) (res1, res2 int) { return }

func main(){}

下面定义了一个结构体类型和它的方法。

        解释:首先我们定义了一个叫做User的结构体类型,然后定义了一个该类型的方法Notice,该方法的接收者是一个User类型的值。要调用Notice方法,我们需要一个User类型的值或者指针。 

        在例子中,当我们使用指针时,Go调整成解引用使得调用可以被执行。

        注意:当接收者不是一个指针时,该方法操作对应接收者值的副本。意思是即使你使用指针调用方法,但方法的接收者是值类型,方法内部的操作还是对副本进行操作,不会修改原来的值。

         我们修改Notice方法,让他的接收者变成指针类型。

        注意:当接收者是指针,即使使用值类型调用方法,方法内部也是对指针操作。会修改原来的值。

  • 方法不过是特殊的函数,只需要将其还原,就知道receiver T和*T的差别

        1.2 普通函数与方法区别

  • 对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然
  • 对于方法,接收者为值类型,可以直接使用指针类型的变量调用方法,反过来也可以。
package main

import "fmt"

//普通函数
//接收者为值类型
func valueIntTest(a int) int {
	return a + 10
}

//接收者为指针类型
func pointIntTest(a *int) int {
	return *a + 10
}

func testValue() {
	a := 10
	fmt.Println(valueIntTest(a))
	//不能传递指针 如:valueIntTest(&a)

	b := 20
	fmt.Println(pointIntTest(&b))
	//不能传递值 如:pointIntTest(b)
}

//结构体
type Data struct {
	x int
}

func (d Data) valueShowData() {
	fmt.Println(d.x)
}

func (d *Data) pointShowData() {
	fmt.Println(d.x)
}

func testStruct() {
	//值类型调用方法
	d1 := Data{x: 10}
	d1.valueShowData()
	d1.pointShowData()

	//指针类型调用方法
	d2 := &Data{x: 100}
	d2.valueShowData()
	d2.pointShowData()
}

func main() {
	testValue()
	testStruct()
}

二. 匿名字段

        Golang匿名字段:可以像字段成员那样访问匿名字段方法,编译器负责查找。

        Go语言是通过嵌套来实现继承的,依据编译器查找次序,只需要在外层定义同名方法,就可以实现继承的隐藏。

三. 方法集

        Golang的方法集:每个类型都有与之关联的方法集,这会影响到接口的实现规则。

  • 类型T方法集包含全部receiver T的方法
  • 类型*T方法集包含全部receiver T + *T方法
  • 如类型S包含匿名字段T,则S和*S方法集包含T的方法
  • 如类型S包含匿名字段*T,则S和*S方法集包含T + *T方法
  • 不管嵌入T或*T,*S方法集总是包含T + *T方法

        用实例value和pointer调用方法(含其它自定义类型)不受方法集的约束,编译器总是查找全部方法,并自动转换reveiver实参。

        方法集和调用方法没有关系。方法集是Go语言中实现面向对象编程特性的关键概念之一,它允许开发者为自定义类型定义行为,并通过接口来实现多态。同时,方法集也是Go语言类型系统和接口系统中不可或缺的一部分。

  • Go语言中内部类型方法提升的规则

        类型T方法集包含全部receiver T的方法。

        类型*T方法集包含全部receiver T + *T方法。

        给定结构体类型S和一个命名为T的类型,方法提升像下面规定的这样被包含在结构体方法集中:

        如类型S包含匿名字段T,则S和*S方法集包含T方法。

        这条规则说的是当我们嵌入一个值类型嵌入类型的接收者为值类型的方法将被提升,可以被外部类型的值和指针调用。

        如类型S包含匿名字段*T,则S和*S方法集包含T+*T方法。

        这条规则说的是当我们嵌入一个类型的指针,嵌入类型的接收者为值类型或者指针类型的方法将被提升,可以被外部类型的值或指针调用

四. 表达式

        Golang表达式:根据调用者不同,方法分为两种表现形式。

  1. object.method(arg...)
  2. type.method(arg...)

        前者称为method value,后者method expression。两者都可像普通函数那样赋值和传参,区别在于method value绑定实例,而method expression则需显示传参。

  •  method value会复制receiver

在汇编层面上,method value和闭包的实现方式相同,实际返回FuncVal类型对象。

FuncVal { method_address, receiver_copy }
  • 可依据方法集转换method expression,注意receiver类型的差异

  • 将方法还原成函数,就是下面的代码
package main

type User struct{}

func (User) TestValue() {}

func (*User) TestPoint() {}

func main() {
	var u *User = nil
	u.TestPoint()

	(*User)(nil).TestPoint() //method value,对象为nil
	(*User).TestPoint(nil)   //method expression,传的对象为nil
}

五. 自定义error

        5.1 抛异常和处理异常

        5.1.1 抛异常

package main

import "fmt"

//系统抛异常
func test01() {
	a := [5]int{1, 2, 3, 4}
	a[1] = 123
	fmt.Println(a)

	index := 10
	a[index] = 10
	fmt.Println(a)
}

func getCircleArea(radius float32) float32 {
	if radius < 0 {
		panic("半径不能为负") //自己抛异常
	}

	return 3.14 * radius * radius
}

func test02() {
	getCircleArea(-5)
}

//捕获异常
func test03() {
	//回收异常
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()

	test02()
	fmt.Println("这里不执行")
}

func test04() {
	test03()
	fmt.Println("test04")
}

func main() {
	test04()

	test01()
}

        5.1.2 返回异常

        5.2 自定义错误

 

 

 

        

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/526740.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Error】Uncaught TypeError: Cannot read properties of undefined (reading ‘get’)

报错原因&#xff1a; 返回值为undefined 解决&#xff1a; vue3可用&#xff1f;

HarmonyOS时区和语言设置-使用相关api实现系统语言和地区设置

介绍 本示例展示了i18n&#xff0c;intl&#xff0c;resourceManager在eTS中的使用&#xff0c;使用相关api实现系统语言和地区设置、时间和时区设置&#xff0c;展示了区域格式化示例。 效果预览 使用说明 1.启动应用&#xff0c;进入应用&#xff0c;首页分为三个按钮&…

谷歌DeepMind发布Gecko:专攻检索,与大7倍模型相抗衡

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 Gecko 是一种通用的文本嵌入模型&#xff0c;可用于训练包括文档检索、语义相似度和分类等各…

JavaScript(三)-Web APIS

文章目录 DOM事件进阶事件流事件流与两个阶段说明事件捕获事件冒泡阻止冒泡解绑事件 事件委托其他事件页面加载事件元素滚动事件页面尺寸事件 元素尺寸与位置 DOM事件进阶 事件流 什么是事件流 事件流指的是事件完整执行过程中的流动路径 事件流与两个阶段说明 捕获与冒泡 …

正确使用@Autowired

目录 一、前言二、跟着官方文档&#xff0c;学习正确使用Autowired0、实验环境1、通过构造方法进行注入1.1 问题1&#xff1a;那万一没有这个CustomerPreferenceDao对象&#xff0c;会报错吗&#xff1f; 2、通过setter方法注入3、通过方法注入&#xff08;这个方法可以是任意名…

iOS 开发中上传 IPA 文件的方法(无需 Mac 电脑

引言 在 iOS 开发中&#xff0c;将 IPA 文件上传到苹果开发者中心是一个重要的步骤。通常情况下&#xff0c;我们需要使用 Mac 电脑上的 Xcode 或 Application Loader 工具来完成这个任务。然而&#xff0c;如果你没有 Mac 电脑&#xff0c;也没有关系&#xff0c;本文将介绍一…

【安全工具】信息收集——ENScan_GO

1.初次使用 运行命令生成配置文件 ./enscan -v 2.配置cookie 参考介绍 wgpsec/ENScan_GO: 一款基于各大企业信息API的工具&#xff0c;解决在遇到的各种针对国内企业信息收集难题。一键收集控股公司ICP备案、APP、小程序、微信公众号等信息聚合导出。 (github.com) 3.友情提…

element-ui 在Popover弹框中使用Select选择器,Vue3

bug描述&#xff1a; 当选择完select的时候,popover也会退出。 解决&#xff1a; popover组件的的关闭是当点击组件外的元素时会关闭&#xff0c;select虽然是写在组件内的&#xff0c;但是select有一个默认属性teleported“true” 会把它默认插到 body 元素&#xff0c;我…

JavaScript模块化开发的前世今生

一个兜兜转转&#xff0c;从“北深”回到三线城市的小码农&#xff0c;热爱生活&#xff0c;热爱技术&#xff0c;在这里和大家分享一个技术人员的点点滴滴。欢迎大家关注我的微信公众号&#xff1a;果冻想 前言 现代化的编程语言&#xff0c;基本都支持模块化的开发&#xff…

嵌入式会越来越卷吗?

当谈及嵌入式系统时&#xff0c;我们探究的不仅是一种科技&#xff0c;更是一个日益多元与普及的趋势。嵌入式系统&#xff0c;作为一种融入更大系统中的计算机硬件和软件&#xff0c;旨在执行特定功能或任务。但这个看似特定的系统概念&#xff0c;却在发展中展现出了惊人的灵…

C++设计模式:观察者模式(三)

1、定义与动机 观察者模式定义&#xff1a;定义对象间的一种1对多&#xff08;变化&#xff09;的依赖关系&#xff0c;以便当一个对象&#xff08;Subject&#xff09;的状态发生比改变时&#xff0c;所有依赖于它的对象都得到通知并且自动更新 再软件构建过程中&#xff0c…

(文章复现)基于改进秃鹰算法的微电网群经济优化调度研究

参考文献&#xff1a; [1]周辉,张玉,肖烈禧,等.基于改进秃鹰算法的微电网群经济优化调度研究[J].太阳能学报,2024,45(02):328-335. 1.基本原理 微电网群由3个独立的微电网(microgrid , MG)组成,各微电网内部包含光伏(photovoltaic , PV)、风力发电机(windturbine,WT)、电动汽…

h5 笔记3 多媒体素材运用

关于电影编码 我们经常用扩展名来判断文件的类型&#xff0c;但是对于影音文件未必适用&#xff0c;影音文件的文件格式(container)和编码(codec)之间并非绝对相关。决定影音文件播放的关键在于浏览器是否含有适合的影音编解码技术。 笔记来源&#xff1a; ©《HTML5CSS3J…

机器学习笔记 - 深度学习遇到超大图像怎么办?使用 xT 对极大图像进行建模论文简读

作为计算机视觉研究人员,在处理大图像时,避免不了受到硬件的限制,毕竟大图像已经不再罕见,手机的相机和绕地球运行的卫星上的相机可以拍摄如此超大的照片,遇到超大图像的时候,我们当前最好的模型和硬件都会达到极限。 所以通常我们在处理大图像时会做出两个次优选择之一:…

Centos 7 安装通过yum安装google浏览器

在CentOS 7上使用yum安装Google Chrome浏览器稍微复杂一些&#xff0c;因为Chrome并不直接包含在默认的Yum仓库中。按照以下步骤来操作&#xff1a; 1、添加Google Chrome仓库 首先&#xff0c;您需要手动添加Google Chrome的Yum仓库。打开终端&#xff0c;并使用文本编辑器&a…

物联网实战--驱动篇之(四)LoRa应用(modbus)

目录 一、前言 二、板级收发 三、主机请求 四、从机接收及回复 五、主机接收 一、前言 之前两篇分别介绍了modbus和sx1278的驱动&#xff0c;但是都并未具体讲解如何应用&#xff0c;那么这一篇就把两者结合起来&#xff0c;做个小demo&#xff0c;便于理解这两个驱动的使…

2005-2023年各省国内生产总值指数分季度数据

2005-2023年各省国内生产总值指数分季度数据 1、时间&#xff1a;2005-2023年 2、来源&#xff1a;国家统计局、各省统计局 3、指标&#xff1a;地区生产总值指数(上年同期100)_累计值(%) 4、范围&#xff1a;31省 5、时间跨度&#xff1a;季度 6、缺失情况&#xff1a;无…

20240325-1-HMM

HMM 直观理解 马尔可夫链&#xff08;英语&#xff1a;Markov chain&#xff09;&#xff0c;又称离散时间马尔可夫链&#xff08;discrete-time Markov chain&#xff0c;缩写为DTMC&#xff09;&#xff0c;因俄国数学家安德烈马尔可夫&#xff08;俄语&#xff1a;Андре…

Ubuntu 20.04.06 PCL C++学习记录(十六)

[TOC]PCL中点云分割模块的学习 学习背景 参考书籍&#xff1a;《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,&#xff0c;PCL版本为1.10.0&#xff0c;CMake版本为3.16 学习内容 用一组点云数据做简单的平面的分割 源代码及所用函数 源代码 #include<iostr…

Linux 内核:线程的实现

在linux中的线程是轻量级线程&#xff08;Light-Weight-process&#xff0c;LWP&#xff09; 文章目录 线程概念线程实现 线程概念 线程分类 用户级线程内核级线程&#xff0c;没有用户空间&#xff0c;完全工作在内核中&#xff08;下图中没有[]的就是用户级线程&#xff09…