什么是方法

一个方法只是一个函数,它有一个特殊的接收者(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,并打印它的 namecurrency 以及 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教程:方法的更多相关文章

  1. GoLang之方法与接口

    GoLang之方法与接口 Go语言没有沿袭传统面向对象编程中的诸多概念,比如继承.虚函数.构造函数和析构函数.隐藏的this指针等. 方法 Go 语言中同时有函数和方法.方法就是一个包含了接受者的函数 ...

  2. Golang之方法(自定义类型,struct)

    方法的使用,请看本天师的代码 //Golang的方法定义 //Golang中的方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,不仅仅是struct //定义:func (recevier ...

  3. C#图解教程-方法参数笔记(上)

    一晃大学四年要过去了,期间乱点了很多技能点, 导致每一项技能都只是处于入门阶段.为了将C#作为我的主要技能,准备恶补相关姿势(知识),通过各种技术论坛的推荐,找到了<C#图解教程>这本书. ...

  4. Golang的方法传递值应该注意的地方

    其实最近看了不少Golang接口以及方法的阐述都有一个地方没说得特别明白.就是在Golang编译隐式转换传递给方法使用的时候,和调用函数时的区别. 我们都知道,在我们为一个类型变量申明了一个方法的时候 ...

  5. python 爬虫系列教程方法总结及推荐

    爬虫,是我学习的比较多的,也是比较了解的.打算写一个系列教程,网上搜罗一下,感觉别人写的已经很好了,我没必要重复造轮子了. 爬虫不过就是访问一个页面然后用一些匹配方式把自己需要的东西摘出来. 而访问页 ...

  6. Golang教程:数组和切片

    数组 数组是类型相同的元素的集合.例如,整数 5, 8, 9, 79, 76 的集合就构成了一个数组.Go不允许在数组中混合使用不同类型的元素(比如整数和字符串). 声明 var variable_n ...

  7. Golang教程:包

    什么是包?为什么使用包? 到目前为止我们见到的 Go 程序都只有一个文件,文件中包含了一个main函数和几个其他函数.在实际中这种将所有代码都放在一个文件里的组织方式是不可行的.这样的组织方式使得代码 ...

  8. Golang教程:类型

    下面是 Go 支持的基本类型: bool Numeric Types  int8, int16, int32, int64, int uint8,uint16,uin32,uint64, uint f ...

  9. Golang教程:变量

    声明单一变量 声明一个变量的语法为:var name type,例如 package main import "fmt" func main() { var age int // ...

随机推荐

  1. I-team 博客的 gitlab-runner 持续集成实践

    做为一个略微看过nodejs语法,但又不懂nodejs的攻城狮,搭建hexo环境很是麻烦,要考虑到FQ版本兼容等问题.于是乎,博主每换一个电脑,为了能继续发博客,都需要在新电脑上花一天时间重新搞一下 ...

  2. vim 插入时间戳的方法

    这里主要说明用内置函数 strftime 来插入,而不用 :r!date 或类似方法. 用命令 "=strftime('%c')<Ret>p ,或<C-r>=strf ...

  3. pandas如何统计所有列的空值,并转化为list?

    统计所有列的空值:data.isnull().sum() 转化成list: df.isnull().sum().index.tolist() df.isnull().sum().values.toli ...

  4. jmeter聚合报告详解

    聚合报告(aggregate report) 对于每个请求,它统计响应信息并提供请求数,平均值,最大,最小值,错误率,大约吞吐量(以请求数/秒为单位)和以kb/秒为单位的吞吐量. 吞吐量是以取样目标点 ...

  5. [译文]casperjs的API-colorizer模块

    colorizer模块包含了一个Colorizer类,它能够生成一个标准化的颜色字符串: var colorizer = require('colorizer').create('Colorizer' ...

  6. python模块之——tqdm(进度条)

    from tqdm import tqdm for i in tqdm(range(10000)): """一些操作""" pass 效果: ...

  7. inception_web

    1) wget --no-check-certificate https://bootstrap.pypa.io/ez_setup.py 2) python ez_setup.py --insecur ...

  8. The score of 'O' and 'X'

    题目描述 注意要点: 使用strlen函数注意加头文件#inlcude <cstring> 循环宏定义for循环#define _for(i,a,b) for(int i=(a);i< ...

  9. 编程开发之--Oracle数据库--存储过程和存储函数(1)

    1.存储过程和存储函数 描述:指存储在数据库中供所有用户程序调用的子程序叫做存储过程.存储函数 区别:存储函数可以通过return子句返回一个函数的值 (1)存储过程 语法:create [or re ...

  10. Windows/Ubuntu下,将所有文件名字列举出来并保存到txt文件中

    Windows下 使用如下的DOS命令来实现: dir /s /b > lists.txt 可以将当前路径下的所有文件的"文件路径+文件名"存储在lists.txt中. 其中 ...