什么是方法

一个方法只是一个函数,它有一个特殊的接收者(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. BlangenOA项目展示(附源码)

    1. 登录界面 1.1表单校验 1.2信息有误 1.3正在登录   2.桌面 3.用户管理 3.1添加 3.2删除 3.3编辑 3.4设置用户角色 3.5设置用户权限 4.角色管理 5.权限管理(菜单 ...

  2. linux命令之文件系统管理命令(下)

    1.mount:挂载文件系统 该命令可以将指定的文件系统挂载到指定目录(挂载点),在linux中必须先挂载所有的设备,才能够访问,挂载的目录必须事先存在并且最好为空. 参数 说明 -t(常用) 指定挂 ...

  3. fdisk 磁盘分区

    .[root@test4 ~]# fdisk /dev/sda //对sda磁盘进行分区 Device contains neither a valid DOS partition table, no ...

  4. Tomcat企业级应用

    简介 Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开发而成.由 ...

  5. 极光开发者沙龙 JIGUANG MEETUP —— 移动应用性能优化实践

    活动背景 移动互联网时代,各大互联网公司都已将自己的产品和服务全面移动化,各类新产品功能都会优先在移动 App 上尝试. 应用性能作为影响用户体验最重要的因素,在开发过程中显得尤为重要. 用户网络环境 ...

  6. 纯css使div垂直居中,div垂直,div居中的方法

    首先编写一个简单的html代码,设置一个父div类名为boxFather,再设置一个子div类名为box1.html代码如下: <div class="boxFather"& ...

  7. Angular material mat-icon 资源参考_Places

    ul,li>ol { margin-bottom: 0 } dt { font-weight: 700 } dd { margin: 0 1.5em 1.5em } img { height: ...

  8. docker images 按名称过滤

    docker images nihao_* 列出所有 nihao_* 正则匹配的镜像

  9. QRegExp

    这段代码会越界,百思不得七姐(过了N久时间 之后^^)原来是把i写成了1  --! //#if 0 QRegExp re1("AT+CGATT?"); QRegExp re2(&q ...

  10. 向指定url发送请求与获取响应

    string url = @"https://www.baidu.com"; //向指定服务器发起请求 HttpWebRequest request = (HttpWebReque ...