Golang教程:方法
什么是方法
一个方法只是一个函数,它有一个特殊的接收者(receiver)类型,该接收者放在 func 关键字和函数名之间。接收者可以是结构体类型或非结构体类型。可以在方法内部访问接收者。
通过下面的语法创建一个方法:
func (t Type) methodName(parameter list) {
}
上面的代码片段创建了一个名为 methodName 的方法,该方法有一个类型为 Type 的接收者。
例子
让我们编写一个简单的程序,它创建一个结构体类型的方法并调用它。
package main import (
"fmt"
) type Employee struct {
name string
salary int
currency string
} /*
displaySalary() method has Employee as the receiver type
*/
func (e Employee) displaySalary() {
fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
} func main() {
emp1 := Employee {
name: "Sam Adolf",
salary: ,
currency: "$",
}
emp1.displaySalary() //Calling displaySalary() method of Employee type
}
上面程序的第 6 行,我们创建了 Employee 的一个名为 displaySalary 的方法。在 displaySalary() 方法内部可以访问它的接收者 e (类型为 Employee)。在第 17 行,我们使用接收者 e,并打印它的 name,currency 以及 salary。
在第26行,我们使用 emp1.displaySalary() 这样的语法来调用方法。
程序的输出为:Salary of Sam Adolf is $5000。
为什么使用方法而不是函数?
上面的程序可以使用函数而不是方法重写如下
package main import (
"fmt"
) type Employee struct {
name string
salary int
currency string
} /*
displaySalary() method converted to function with Employee as parameter
*/
func displaySalary(e Employee) {
fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
} func main() {
emp1 := Employee{
name: "Sam Adolf",
salary: ,
currency: "$",
}
displaySalary(emp1)
}
在上面的程序中,我们使用 displaySalary 函数替换了方法,并将 Employee 结构体作为参数传给它。该程序的输出与上面的程序输出一样:Salary of Sam Adolf is $5000。
为什么使用方法而不是函数?
上面的程序可以使用函数而不是方法重写如下:
package main import (
"fmt"
) type Employee struct {
name string
salary int
currency string
} /*
displaySalary() method converted to function with Employee as parameter
*/
func displaySalary(e Employee) {
fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
} func main() {
emp1 := Employee{
name: "Sam Adolf",
salary: ,
currency: "$",
}
displaySalary(emp1)
}
在上面的程序中,我们使用 displaySalary 函数替换了方法,并将 Employee 结构体作为参数传给它。该程序的输出与上面的程序输出一样:Salary of Sam Adolf is $5000。
那么为什么我们可以用函数完成同样的工作,却还要使用方法呢?这里有几个原因,我们一个一个地看。
- Go 不是一个纯面向对象的编程语言,它不支持 class 类型。因此通过在一个类型上建立方法来实现与 class 相似的行为。
- 同名方法可以定义在不同的类型上,但是 Go 不允许同名函数。假设我们有一个
Square和Circle两个结构体。在Square和Circle上定义同名的方法是合法的,比如下面的程序:
package main import (
"fmt"
"math"
) type Rectangle struct {
length int
width int
} type Circle struct {
radius float64
} func (r Rectangle) Area() int {
return r.length * r.width
} func (c Circle) Area() float64 {
return math.Pi * c.radius * c.radius
} func main() {
r := Rectangle{
length: ,
width: ,
}
fmt.Printf("Area of rectangle %d\n", r.Area())
c := Circle{
radius: ,
}
fmt.Printf("Area of circle %f", c.Area())
}
程序的输出为:
Area of rectangle
Area of circle 452.389342
定义非结构体类型的方法
现在我们定义的都是结构体类型的方法。同样可以定义非结构体类型的方法,不过这里需要注意一点。为了定义某个类型的方法,接收者类型的定义与方法的定义必须在同一个包中。目前为止,我们定义的结构体和相应的方法都是在main包中的,因此没有任何问题。
package main
func (a int) add(b int) {
}
func main() {
}
在上面的程序中,第3行我们试图添加一个方法 add 给内置类型 int。这是不允许的,因为定义方法 add 所在的包和定义类型 int 的包不是同一个包。这个程序将会报编译错误:cannot define new methods on non-local type int。
使其工作的方法为定义内置类型的别名,然后以这个新类型为接收者创建方法。
package main
import "fmt"
type myInt int
func (a myInt) add(b myInt) myInt {
return a + b
}
func main() {
num1 := myInt()
num2 := myInt()
sum := num1.add(num2)
fmt.Println("Sum is", sum)
}
上面的程序中,第5行,我们创建了新的类型,一个 int 的别名 myInt。在第7行,我们定义了一个方法 add,以 myInt作为接收者。
程序的输出为: Sum is 15。
Golang教程:方法的更多相关文章
- GoLang之方法与接口
GoLang之方法与接口 Go语言没有沿袭传统面向对象编程中的诸多概念,比如继承.虚函数.构造函数和析构函数.隐藏的this指针等. 方法 Go 语言中同时有函数和方法.方法就是一个包含了接受者的函数 ...
- Golang之方法(自定义类型,struct)
方法的使用,请看本天师的代码 //Golang的方法定义 //Golang中的方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,不仅仅是struct //定义:func (recevier ...
- C#图解教程-方法参数笔记(上)
一晃大学四年要过去了,期间乱点了很多技能点, 导致每一项技能都只是处于入门阶段.为了将C#作为我的主要技能,准备恶补相关姿势(知识),通过各种技术论坛的推荐,找到了<C#图解教程>这本书. ...
- Golang的方法传递值应该注意的地方
其实最近看了不少Golang接口以及方法的阐述都有一个地方没说得特别明白.就是在Golang编译隐式转换传递给方法使用的时候,和调用函数时的区别. 我们都知道,在我们为一个类型变量申明了一个方法的时候 ...
- python 爬虫系列教程方法总结及推荐
爬虫,是我学习的比较多的,也是比较了解的.打算写一个系列教程,网上搜罗一下,感觉别人写的已经很好了,我没必要重复造轮子了. 爬虫不过就是访问一个页面然后用一些匹配方式把自己需要的东西摘出来. 而访问页 ...
- Golang教程:数组和切片
数组 数组是类型相同的元素的集合.例如,整数 5, 8, 9, 79, 76 的集合就构成了一个数组.Go不允许在数组中混合使用不同类型的元素(比如整数和字符串). 声明 var variable_n ...
- Golang教程:包
什么是包?为什么使用包? 到目前为止我们见到的 Go 程序都只有一个文件,文件中包含了一个main函数和几个其他函数.在实际中这种将所有代码都放在一个文件里的组织方式是不可行的.这样的组织方式使得代码 ...
- Golang教程:类型
下面是 Go 支持的基本类型: bool Numeric Types int8, int16, int32, int64, int uint8,uint16,uin32,uint64, uint f ...
- Golang教程:变量
声明单一变量 声明一个变量的语法为:var name type,例如 package main import "fmt" func main() { var age int // ...
随机推荐
- Backup--完整备份会打破现有的日志备份链么?
--问题描述: --对数据库有一个周期性数据库备份和事务日志备份的维护计划,在维护计划外有工作人员对数据库进行完整备份,该备份会打乱现有的日志备份链么? --===================== ...
- border使用小技巧
border-style 分类 dashed虚线类型 dotted 点线类型 double 双线类型 双线型量根实线的宽度和中间空白区域的间距有一定规律: 可以利用这个规律画出一些特殊的图案 代码如下 ...
- centos7 minimal 安装mysql
CentOS 7.3.1611 安装 MySQL 2017年06月08日 23:02:08 阅读数:250 依赖 MySQL 依赖 libaio,所以先要安装 libaio yum search ...
- sqlserver 事务日志已满解决方案
sqlserver 事务日志已满解决方案 可参考这篇博客: https://www.cnblogs.com/strayromeo/p/6961758.html 一.删除日志文件:(不建议) 二.手动收 ...
- Android应用-底部导航栏的使用
目录 1. 设计底部导航栏页面 1.1. 创建必须的文件夹 1.2. 设计主页面 2. 设计逻辑函数 3. 项目展示 底部导航栏是基于Bottom Navigation Bar 插件使用的 这个插件包 ...
- Windows server 2008 R2中安装MySQL !
我今天打算在Windows server 2008 R2中安装MySQL,可是总是发现ODBC连接器安装错误,无论我采用MySQL的整体安装包,还是单独的ODBC连接器安装文件!! 最后上网搜索了很久 ...
- linux 查看进程所在目录
一下内容转自:https://blog.csdn.net/spring21st/article/details/50561550 通过 ps 及 top 命令查看进程信息时,只能查到 相对路径,查不到 ...
- leecode刷题(15)-- 验证回文字符串
leecode刷题(15)-- 验证回文字符串 验证回文字符串 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 ...
- iOS核心动画之视觉效果
圆角 cornerRadius确定圆角的大小 masksToBounds确定要不要裁减圆角以外的界面 图层边框 borderWidth 边框的粗细,point是衡量值. borderColor 边框的 ...
- win10打开移动热点让手机连接上网教程
概述: 为什么要这么做呢? 我笔记本插网线可以上网,但是没有买猫盒,所以只能pc开热点,让手机上网. 过程如下: 1开启移动热点,设置密码 1.1开启移动热点,截图如下: 1.2设置热点名称,密码 2 ...