什么是方法

一个方法只是一个函数,它有一个特殊的接收者(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. Web Server 在IIS上部署ASP.NET Core项目

    在IIS上部署ASP.NET Core项目 一.配置应用程序池为无托管: 二.安装ASPNETCoreModule:(核心) 下载地址:https://go.microsoft.com/fwlink/ ...

  2. 快速排序 java实现 (原理-优化) 三路快排

    一.基本的快速排序 在数组中选取一个元素为基点,然后想办法把这个基点元素移动到它在排好序后的最终位置,使得新数组中在这个基点之前的元素都小于这个基点,而之后的元素都大于这个基点,然后再对前后两部分数组 ...

  3. 「NOIP 2013」 货车运输

    题目链接 戳我 \(Solution\) 这一道题直接用\(kruskal\)重构树就好了,这里就不详细解释\(kruskal\)重构树了,如果不会直接去网上搜就好了.接下来讲讲详细过程. 首先构建\ ...

  4. 【ocp 052又加新题了】052新加的考试题及答案整理-第13题

    13.Which two are true about AWR snapshots? A) They are stored In the SYSAUX tablespace. B) They are ...

  5. binlog2sql

    从MySQL binlog解析出你要的SQL.根据不同选项,你可以得到原始SQL.回滚SQL.去除主键的INSERT SQL等. 安装 shell> git clone https://gith ...

  6. PHP如何将多维数组中的数据批量插入数据库?

    PHP将多维数组中的数据批量插入到数据库中,顾名思义,需要用循环来插入. 1.循环insert into 语句,逐渐查询 <?php /* www.qSyz.net */ @mysql_conn ...

  7. mycat 1.6.6.1 distinct报错问题

    以前在mysql5.7上执行如下sql语句没有问题 SELECT DISTINCT u.*,c.content userCategory FROM m_user u LEFT JOIN m_categ ...

  8. iptables总结

        iptables: 包过滤型防火墙      Firewall: 防火墙,隔离工具:工作于主机或网络的边缘,对于进出本主机或网络的报文根据事先定义好的检查规则作匹配检测,对于能够被规则所匹配到 ...

  9. hdfs shell的基本操作以及hdfsWeb查看文件

    在安装好hadoop集群并成功的启动了hdfs之后,我们就可以利用hdfs对文件进行操作了,一下是对文件的一些基本操作 hdfs基本操作 1.查询命令 hadoop dfs -ls /   查询/目录 ...

  10. executeQueryForObject returned too many results.

    //错误位置: 这个错误出现在持久层与数据库交互时,原因是 queryForObject这个方法封装唯一值,但是给出的sql语句返回了多个值 public int getListCount(SqlMa ...