zoukankan      html  css  js  c++  java
  • 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:   5000,
            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:   5000,
            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:   5000,
            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: 10,
              5,
        }
        fmt.Printf("Area of rectangle %d
    ", r.Area())
        c := Circle{
            radius: 12,
        }
        fmt.Printf("Area of circle %f", c.Area())
    }

    程序的输出为:

    Area of rectangle 50  
    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(5)
        num2 := myInt(10)
        sum := num1.add(num2)
        fmt.Println("Sum is", sum)
    }

    上面的程序中,第5行,我们创建了新的类型,一个 int 的别名 myInt。在第7行,我们定义了一个方法 add,以 myInt作为接收者。

    程序的输出为: Sum is 15

  • 相关阅读:
    MySQL 和 Oracle 在 MyBatis 使用中的区别
    nodeppt:网页版 PPT
    在 sql 语句出现 warning 之后,立刻执行 `show warnings;` 就可以看到 warning 提示信息
    MySQL 列,可选择的数据类型(通过sql命令查看:`help create table;`)
    create table 推荐规则
    MySQL 中的变量:系统变量(包括:会话变量、全局变量)、用户变量(包括:局部变量、用户变量)
    MySQL 有用的查询语句
    MySQL 遇到错误集锦
    VARCHAR(N)类型,utf8编码,则N最大值为多少,n表示什么?
    MySQL 的严格模式
  • 原文地址:https://www.cnblogs.com/liuzhongchao/p/9183746.html
Copyright © 2011-2022 走看看