李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
GO
正文
16.Golang方法和函数区别
Leefs
2022-07-06 AM
957℃
0条
[TOC] ### 前言 ![16.Golang方法和函数区别01.jpeg](https://lilinchao.com/usr/uploads/2022/07/3927809201.jpeg) 在前面的章节中介绍过了Golang中的方法和函数,但是如果不进行比较,对于两者的认识还是很容易产生混淆。 ### 一、概述 Go语言支持方法。Go方法与Go函数相似,但有一点不同,**方法就是一个包含了接收者参数的函数**。 + **在接收者参数的帮助下,该方法可以访问接收者的属性。** + **接收方可以是结构类型或非结构类型。** + **在代码中创建方法时,接收者和接收者类型必须出现在同一个包中。**而且不允许创建一个方法,其中的接收者类型已经在另一个包中定义,包括像int、string等内建类型。如果您尝试这样做,那么编译器将抛出错误。 **语法** ```go func(reciver_name Type) method_name(parameter_list)(return_type){ // Code } ``` 在此,可以在方法内访问接收器。 **示例** ```go type person struct { name string age int8 } //函数,求和 func sum(x,y int) int { return x + y } //方法 func (p person) String() string{ return fmt.Sprintf("姓名:%s\n年龄:%d",p.name,p.age) } func main() { //初始化并调用方法 p := person{name:"Leefs",age:18} fmt.Println(p.String()) //调用函数 x,y := 10,20 s := sum(x,y) fmt.Printf("sum=%d\n",s) } ``` **运行结果** ``` 姓名:Leefs 年龄:18 sum=30 ``` **总结** **方法在定义的时候,会在`func`和方法名之间增加一个参数,这个参数就是接收者,这样我们定义的这个方法就和接收者绑定在了一起,称之为这个接收者的方法。** ### 二、同名方法 在 Go 中,相同的名字的方法可以定义在不同的类型上,而相同名字的函数是不被允许的。如果在GO语言程序中添加一个同名函数,就会报错。但是在不同的结构体上面定义同名的方法就是可行的。 ```go type person struct { name string age int8 } //同名方法,返回姓名和年龄 func (p person) String() string { return fmt.Sprintf("姓名:%s,年龄:%d",p.name,p.age) } type student struct { name string } //同名方法,返回学生姓名 func (s student) String() string{ return fmt.Sprintf("学生姓名:%s",s.name) } func main() { p := person{name: "Leefs",age: 18} fmt.Println(p.String()) s := student{name: "Jeyoo"} fmt.Println(s.String()) } ``` **运行结果** ``` 姓名:Leefs,年龄:18 学生姓名:Jeyoo ``` ### 三、值传递和引用传递 *该小节在文章《Golang结构体(二)》中已经做了详细介绍* + **值传递**:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。 + **引用传递**:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。 **示例** ```go type person struct { name string } //值传递 func (p person) changeName(name string){ p.name = name } //引用传递 func (p *person) changeNamePointer(name string){ p.name = name } func main() { p := person{name:"Leefs"} fmt.Printf("原始名称:%s\n",p.name) //修改失败 p.changeName("Took") fmt.Printf("通过值传递修改名称:%s\n",p.name) //修改成功 p.changeNamePointer("Jeyoo") fmt.Printf("通过引用传递修改名称:%s\n",p.name) } ``` **运行结果** ``` 原始名称:Leefs 通过值传递修改名称:Leefs 通过引用传递修改名称:Jeyoo ``` 在调用方法的时候,传递的接收者本质上都是副本,只不过一个是这个值副本,一是指向这个值指针的副本。指针具有指向原有值的特性,所以修改了指针指向的值,也就修改了原有的值。我们可以简单的理解为值接收者使用的是值的副本来调用方法,而指针接收者使用实际的值来调用方法。 ### 四、在方法中使用值接收器与在函数中使用值参数 当一个函数有一个值参数,它只能接受一个值参数。当一个方法有一个值接收器,它可以接受值接收器和指针接收器。 ```go type Lesson struct { Name string } //方法 func (lesson Lesson) PrintInfo() { fmt.Println(lesson.Name) } //函数 func PrintInfo(lesson Lesson) { fmt.Println(lesson.Name) } func main() { lesson := Lesson{"《张宇基础30讲》"} //调用函数 PrintInfo(lesson) //调用方法 lesson.PrintInfo() bPtr := &lesson //调用函数 //PrintInfo(bPtr) // error //调用方法 bPtr.PrintInfo() } ``` 在上面的程序中,使用值参数 `PrintInfo(lesson)` 来调用这个函数是合法的,使用值接收器来调用 `lesson.PrintInfo()` 也是合法的。 然后在程序中我们创建了一个指向 `Lesson` 的指针 `bPtr` ,通过使用指针接收器来调用 `bPtr.PrintInfo()` 是合法的,但使用值参数调用 `PrintInfo(bPtr)` 是非法的。 ### 五、在非结构体上的方法 不仅可以在结构体类型上定义方法,也可以在非结构体类型上定义方法,但是有一个问题。为了在一个类型上定义一个方法,**方法的接收器类型定义和方法的定义应该在同一个包中**。 **示例** ```go package main import "fmt" type myInt int func (a myInt) add(b myInt) myInt { return a + b } func main() { var x myInt = 50 var y myInt = 7 fmt.Println(x.add(y)) // 57 } ``` ### 总结 方法和函数之间的差异: | 方法 | 函数 | | :--------------------------------------- | :--------------------------------------- | | 包含接收器 | 不包含接收器 | | 可以接受指针和值 | 不能同时接受指针和值 | | 可以在程序中定义相同名称但不同类型的方法 | 程序中不允许定义相同名称但不同类型的函数 | *附参考文章链接* *http://www.go-edu.cn/2022/05/20/go-12-%E6%96%B9%E6%B3%95/* *https://www.cainiaojc.com/golang/go-methods.html*
标签:
Golang基础
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/2228.html
上一篇
15.Golang流程控制
下一篇
17.Golang接口介绍
取消回复
评论啦~
提交评论
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
标签云
BurpSuite
Scala
锁
Stream流
gorm
Linux
nginx
数学
Jquery
DataWarehouse
链表
LeetCode刷题
工具
微服务
算法
设计模式
Java阻塞队列
线程池
Ubuntu
Nacos
数据结构和算法
GET和POST
MyBatis
查找
Azkaban
散列
Java编程思想
队列
Spark Streaming
Kibana
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞