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 // ...
随机推荐
- C#winform自定义滚动条
1.控件 一个UserControl作为ScrollBg,一个panel作为ScrollBar 2.实现功能 (1)设置滚动条背景颜色和背景图片 (2)设置滚动条滑块的背景颜色和背景图片 (3)鼠标左 ...
- C#中Attribute/特性的使用
类似Java的注解/Annotation 特性是用于在运行时传递程序中各种元素(比如类.方法.结构.枚举.组件等)的行为信息的声明性标签,这个标签可以有多个.您可以通过使用特性向程序添加声明性信息.一 ...
- MYSQL ZIP 压缩包 安装
基win10安装 1.管理员身份打开cmd 2.进入mysql 的 bin文件下 D: 回车 3.mysql服务名字 -install 回车 4.net start mysql服务名字 ...
- HAOI2010 工厂选址
题目链接:戳我 数组开小火葬场qwqwq 就是一个贪心吧.对于一个数,我们知道只有两种摆放方式.所以我们可以先都放到新的里面,然后做一下新的-原先的差,按照差从大到小排序,依次提取数值减去即可. 代码 ...
- leetcode 23. 合并K个排序链表 JAVA
题目: 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: ...
- Echart自定义y轴刻度信息1
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 4.iptables 网络防火墙
[1] #如果想要iptables作为网络防火墙,iptables所在主机开启核心转发功能,以便能够转发报文. [2] #使用如下命令查看当前主机是否已经开启了核心转发,0表示为开启,1表示已开启 c ...
- CTSC2017酱油记
恩..又是一篇酱油记.. 自从SHTSC完之后都在复习地理高考..根本没有刷题.. 于是就来CTSC了..因为奇怪的实验考..APIO又不能参加..只能拿一块Fe了.. DAY0 恩..不存在DAY0 ...
- Linux常用运维指令
cd data/apps./=========================================== ps -ef | grep tomcatps -ef | grep desktopX ...
- JSR133规范学习
最近在看多线程相关的东西,通过阅读JSR133的faq来加深自己对多线程的理解,里面大部分的内容比较简单(越到后面越难),但是有的部分比较难以理解还没有完全弄懂,所以这里只记录了一下比较简单的阅读笔记 ...