博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go学习(10):方法
阅读量:4060 次
发布时间:2019-05-25

本文共 4574 字,大约阅读时间需要 15 分钟。

一.方法

1.1 什么是方法

Go 语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集

方法只是一个函数,它带有一个特殊的接收器类型,它是在func关键字和方法名之间编写的。接收器可以是struct类型或非struct类型。接收方可以在方法内部访问。

1.2 方法的语法

定义方法的语法

func (t Type) methodName(parameter list) {
}

实例代码:

package mainimport (      "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: 5000, currency: "$", } emp1.displaySalary() //Calling displaySalary() method of Employee type}

可以定义相同的方法名

示例代码:

package mainimport (	"fmt"	"math")type Rectangle struct {
width, height float64}type Circle struct {
radius float64}func (r Rectangle) area() float64 {
return r.width * r.height}//该 method 属于 Circle 类型对象中的方法func (c Circle) area() float64 {
return c.radius * c.radius * math.Pi}func main() {
r1 := Rectangle{
12, 2} r2 := Rectangle{
9, 4} c1 := Circle{
10} c2 := Circle{
25} fmt.Println("Area of r1 is: ", r1.area()) fmt.Println("Area of r2 is: ", r2.area()) fmt.Println("Area of c1 is: ", c1.area()) fmt.Println("Area of c2 is: ", c2.area())}

运行结果

Area of r1 is:  24Area of r2 is:  36Area of c1 is:  314.1592653589793Area of c2 is:  1963.4954084936207
  • 虽然method的名字一模一样,但是如果接收者不一样,那么method就不一样
  • method里面可以访问接收者的字段
  • 调用method通过.访问,就像struct里面访问字段一样

1.3 方法和函数

既然我们已经有了函数,为什么还要使用方法?

示例代码:

package mainimport (      "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: 5000, currency: "$", } displaySalary(emp1)}

在上面的程序中,displaySalary方法被转换为一个函数,而Employee struct作为参数传递给它。这个程序也产生了相同的输出:Salary of Sam Adolf is $5000.。

为什么我们可以用函数来写相同的程序呢?有以下几个原因

  1. Go不是一种纯粹面向对象的编程语言,它不支持类。因此,类型的方法是一种实现类似于类的行为的方法。
  2. 相同名称的方法可以在不同的类型上定义,而具有相同名称的函数是不允许的。假设我们有一个正方形和圆形的结构。可以在正方形和圆形上定义一个名为Area的方法。这是在下面的程序中完成的。

1.4 变量作用域

作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。

Go 语言中变量可以在三个地方声明:

  • 函数内定义的变量称为局部变量
  • 函数外定义的变量称为全局变量
  • 函数定义中的变量称为形式参数

局部变量

在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。

全局变量

在函数体外声明的变量称之为全局变量,首字母大写全局变量可以在整个包甚至外部包(被导出后)使用。

package mainimport "fmt"/* 声明全局变量 */var g intfunc main() {
/* 声明局部变量 */ var a, b int /* 初始化参数 */ a = 10 b = 20 g = a + b fmt.Printf("结果: a = %d, b = %d and g = %d\n", a, b, g)}

结果

结果: a = 10, b = 20 and g = 30

形式参数

形式参数会作为函数的局部变量来使用

指针作为接收者

若不是以指针作为接收者,实际只是获取了一个copy,而不能真正改变接收者的中的数据

func (b *Box) SetColor(c Color) {
b.color = c}

示例代码

package mainimport (	"fmt")type Rectangle struct {
width, height int}func (r *Rectangle) setVal() {
r.height = 20}func main() {
p := Rectangle{
1, 2} s := p p.setVal() fmt.Println(p.height, s.height)}

结果

20 2

如果没有那个*,则值就是2 2

1.5 method继承

method是可以继承的,如果匿名字段实现了一个method,那么包含这个匿名字段的struct也能调用该method

package mainimport "fmt"type Human struct {
name string age int phone string}type Student struct {
Human //匿名字段 school string}type Employee struct {
Human //匿名字段 company string}func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)}func main() {
mark := Student{
Human{
"Mark", 25, "222-222-YYYY"}, "MIT"} sam := Employee{
Human{
"Sam", 45, "111-888-XXXX"}, "Golang Inc"} mark.SayHi() sam.SayHi()}

运行结果:

Hi, I am Mark you can call me on 222-222-YYYYHi, I am Sam you can call me on 111-888-XXXX

1.6 method重写

package mainimport "fmt"type Human struct {
name string age int phone string}type Student struct {
Human //匿名字段 school string}type Employee struct {
Human //匿名字段 company string}//Human定义methodfunc (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)}//Employee的method重写Human的methodfunc (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name, e.company, e.phone) //Yes you can split into 2 lines here.}func main() {
mark := Student{
Human{
"Mark", 25, "222-222-YYYY"}, "MIT"} sam := Employee{
Human{
"Sam", 45, "111-888-XXXX"}, "Golang Inc"} mark.SayHi() sam.SayHi()}

运行结果:

Hi, I am Mark you can call me on 222-222-YYYYHi, I am Sam, I work at Golang Inc. Call me on 111-888-XXXX
  • 方法是可以继承和重写的
  • 存在继承关系时,按照就近原则,进行调用

转载地址:http://xmwji.baihongyu.com/

你可能感兴趣的文章
大数据入门:Zookeeper结构体系
查看>>
大数据入门:Spark RDD基础概念
查看>>
大数据入门:SparkCore开发调优原则
查看>>
大数据入门:Java和Scala编程对比
查看>>
大数据入门:Scala函数式编程
查看>>
C++报错:引发了未经处理的异常:写入访问权限冲突, p 是 0xCCCCCCCC
查看>>
【数据结构周周练】002顺序表与链表
查看>>
C++报错:C4700:使用了非初始化的局部变量
查看>>
【数据结构周周练】003顺序栈与链栈
查看>>
【数据结构周周练】006队列基本操作-顺序结构及链式结构实现
查看>>
C++类、结构体、函数、变量等命名规则详解
查看>>
C++ goto语句详解
查看>>
【数据结构周周练】008 二叉树的链式创建及测试
查看>>
《算法分析与设计》 第七章 贪心法 基本知识点整理
查看>>
贪心法求解背包问题 C++
查看>>
贪心法求解TSP问题 C++
查看>>
《软件体系结构》 第四章 软件体系结构描述
查看>>
《软件体系结构》第六章 Web服务体系结构
查看>>
《软件体系结构》 第七章 基于体系结构的软件开发
查看>>
《软件体系结构》 第九章 软件体系结构评估
查看>>