Golang——方法

news2025/2/23 17:06:39

一. 方法定义

        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 自定义错误

 

 

 

        

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JAVASE】抽象类和接口及其抽象类和接口的区别

✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;再无B&#xff5e;U&#xff5e;G-CSDN博客 目标&#xff1a; 1. 抽象类 2. 接口 3. Object 类 1. &am…

性能测试--数据库慢 SQL 语句分析

一 慢 SQL 语句的几种常见诱因 1. 无索引或索引失效 ​ 当查询基于一个没有索引的列进行过滤、排序或连接时&#xff0c;数据库可能被迫进行全表扫描&#xff0c;即逐行检查所有数据&#xff0c;导致性能显著下降。 ​ 虽然我们很多时候建立了索引&#xff0c;但在一些特定的…

第3章 存储系统(2)

3.3 主存储器与CPU连接 3.3.1 连接原理 现代计算机的MAR和MDR都在CPU内部。 (1)主存储器通过数据总线,地址总线,控制总线与CPU连接。 (2)数据传输率数据总线宽度*总线频率。 (4)控制总线(读写线)控制读写操作。 3.3.2 主存的扩展 数据总线宽度等于存储字长 1.位扩展法【增加…

【软件测试】个人博客系统测试

个人博客系统测试 一、项目背景1.1 技术背景1.2 功能背景 二、自动化测试2.1 什么是自动化测试2.2 通过使用selenium进行自动化测试的编写&#xff08;Java实现&#xff09;2.3 编写测试用例&#xff0c;执行自动化测试2.3.1 输入用户名:test,密码:123&#xff0c;登录成功2.3.…

Java | Leetcode Java题解之第20题有效的括号

题目&#xff1a; 题解&#xff1a; class Solution {public boolean isValid(String s) {int n s.length();if (n % 2 1) {return false;}Map<Character, Character> pairs new HashMap<Character, Character>() {{put(), ();put(], [);put(}, {);}};Deque<…

基于SpringBoot+Vue的工厂生产设备维护管理系统(源码+文档+部署+讲解)

一.系统概述 随着社会的发展&#xff0c;系统的管理形势越来越严峻。越来越多的用户利用互联网获得信息&#xff0c;但各种信息鱼龙混杂&#xff0c;信息真假难以辨别。为了方便用户更好的获得工厂生产设备维护信息&#xff0c;因此&#xff0c;设计一种安全高效的工厂生产设备…

Vue中key的原理以及diff算法

简介&#xff1a;Vue的key用于在虚拟DOM中标记节点&#xff0c;方便后面的diff对比算法进行对比&#xff0c;提升效率。 Vue的vm或者vc实例一共管理着3个DOM对象&#xff0c;分别他的模板对应的真实DOM、真实DOM的备份、以及重新生成的新的DOM&#xff0c;后两个可以看成是虚拟…

Scaffold-GS 代码阅读笔记

1. 系统启动部分 使用 python 中的 parser 库 为配置系统的参数设定, 和3DGS 类似&#xff0c;并且使用safe_state(args.quiet) 函数 为每一次的 log 输出加上对应的 时间戳 ## 配置参数的设定lp ModelParams(parser)op OptimizationParams(parser)pp PipelineParams(pars…

每日一题(leetcode1702):修改后的最大二进制字符串--思维

找到第一个0之后&#xff0c;对于后面的子串&#xff08;包括那个0&#xff09;&#xff0c;所有的0都能调上来&#xff0c;然后一一转化为10&#xff0c;因此从找到的第一个0的位置开始&#xff0c;接下来是&#xff08;后半部分子串0的个数-1&#xff09;个1&#xff0c;然后…

移动WEB开发之响应式布局

一、响应式开发 1、响应式开发原理 就是使用媒体查询针对不同宽度的设备进行布局和样式的设置&#xff0c;从而适配不同设备的目的。 2、响应式布局容器 响应式布局容器需要一个父级作为布局容器&#xff0c;来配合子集元素来实现变化效果。 原理就是在不同屏幕下通过媒体查询…

OpenHarmony 资源调度之内存管理源码分析

作者&#xff1a;张守忠 1 内存管理简介 内存管理部件位于全局资源调度管控子系统中&#xff0c;基于应用的生命周期状态&#xff0c;更新进程回收优先级列表&#xff0c;通过内存回收、查杀等手段管理系统内存&#xff0c;保障内存供给。 1.1 内存管理框架 内存管理部件主要…

你一定不能错过的多模态大模型!阿里千问开源Qwen-VL!具备图文解读等能力

1. Qwen-VL简介 1.1. 介绍 Qwen-VL的多语言视觉语言模型系列,基于Qwen-7B语言模型。该模型通过视觉编码器和位置感知的视觉语言适配器,赋予语言模型视觉理解能力。 Qwen-VL采用了三阶段的训练流程,并在多个视觉语言理解基准测试中取得了领先的成绩。该模型支持多语言、多图…

这一次,阿里能完成变革么

更多精彩内容在公众号。 马云在阿里内网发表题为《致改革 致创新》的帖子。释放支持继续改革信号。全文参考下图 马云在最近的发言中首先引用了阿里巴巴集团董事局主席蔡崇信的一次采访&#xff0c;表示对蔡崇信坦率地承认过去错误的勇敢态度表示赞赏。马云强调&#xff0c;犯错…

【MapBox】实现实时飞行轨迹功能

之前写了一篇MapBox添加带箭头的轨迹线&#xff0c;现在在这个基础之上实现获取到无人机的推送点位数据实时飞行的功能 首先创建实例&#xff0c;将无人机的图标加载在地图上 const MAP_UAV_FLIGHT_ING (values, layerKey 无人机飞行) > {ClearUAVMap();const map GET_…

功能测试_验证新浪邮箱登录的正确性

案例&#xff1a;验证验证新浪邮箱登录的正确性 功能测试_等价类设计用例&#xff1a; 步骤&#xff1a; 1:明确需求&#xff1a;邮箱能否登录 2:划分等价类&#xff1a;有效等价类、有效取值、无效等价类、无效取值 3&#xff1a;提取数据编写用例&#xff1a;用例编号、…

消息队列MQ的介绍和docker安装MQ

一、什么是mq? MQ全称 Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信&#xff0c;解耦。 二、常见的mq产品 RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq RabbitMQ: One broker …

数仓指标体系

数仓指标体系 明确统计指标 明确统计指标具体的工作是&#xff0c;深入分析需求&#xff0c;构建指标体系。构建指标体系的主要意义就是指标定义标准化。所有指标的定义&#xff0c;都必须遵循同一套标准&#xff0c;这样能有效的避免指标定义存在歧义&#xff0c;指标定义重复…

AcWing 1491.圆桌座位 解题思路及代码

看数论看烦了&#xff0c;随便找到题换换脑子&#xff0c;结果就遇到了这题&#xff0c;还挺有意思的&#xff0c;有几个思维难点。 先贴个题目&#xff1a; 以及原题链接&#xff1a;1491. 圆桌座位 - AcWing题库https://www.acwing.com/problem/content/description/1493/ 几…

SpringBoot修改菜品模块开发

需求分析与设计 一&#xff1a;产品原型 在菜品管理列表页面点击修改按钮&#xff0c;跳转到修改菜品页面&#xff0c;在修改页面回显菜品相关信息并进行修改&#xff0c;最后点击保存按钮完成修改操作。 修改菜品原型&#xff1a; 二&#xff1a;接口设计 通过对上述原型图…

linux系统离线安装nginx

介绍&#xff1a;nginx是一个高性能的http和反向代理服务器&#xff0c;并发能力很强&#xff0c;一般用来做负载均衡比较多&#xff0c;日常开发中用作web服务器 说明&#xff1a;本文用到的所有资源&#xff0c;笔者已经打包上传了&#xff0c;需要下载的请于文章顶部下载 …