zoukankan      html  css  js  c++  java
  • Go学习(10):方法

    一.方法

    1.1 什么是方法

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

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

    1.2 方法的语法

    定义方法的语法

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

    实例代码:

    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
    }
    

    可以定义相同的方法名

    示例代码:

    package main
    
    import (
    	"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:  24
    Area of r2 is:  36
    Area of c1 is:  314.1592653589793
    Area of c2 is:  1963.4954084936207
    
    • 虽然method的名字一模一样,但是如果接收者不一样,那么method就不一样
    • method里面可以访问接收者的字段
    • 调用method通过.访问,就像struct里面访问字段一样

    1.3 方法和函数

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

    示例代码:

    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 struct作为参数传递给它。这个程序也产生了相同的输出:Salary of Sam Adolf is $5000.。

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

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

    1.4 变量作用域

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

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

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

    局部变量

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

    全局变量

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

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

    结果

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

    形式参数

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

    指针作为接收者

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

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

    示例代码

    package main
    
    import (
    	"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 main
    
    import "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
    ", 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-YYYY
    Hi, I am Sam you can call me on 111-888-XXXX
    

    1.6 method重写

    package main
    
    import "fmt"
    
    type Human struct {
    	name  string
    	age   int
    	phone string
    }
    type Student struct {
    	Human  //匿名字段
    	school string
    }
    type Employee struct {
    	Human   //匿名字段
    	company string
    }
    
    //Human定义method
    func (h *Human) SayHi() {
    	fmt.Printf("Hi, I am %s you can call me on %s
    ", h.name, h.phone)
    }
    
    //Employee的method重写Human的method
    func (e *Employee) SayHi() {
    	fmt.Printf("Hi, I am %s, I work at %s. Call me on %s
    ", 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-YYYY
    Hi, I am Sam, I work at Golang Inc. Call me on 111-888-XXXX
    
    • 方法是可以继承和重写的
    • 存在继承关系时,按照就近原则,进行调用
  • 相关阅读:
    This project references NuGet package(s) that are missing on this computer
    Industry Engineer
    winform
    OPC
    groupbox 下的datagridview的列标题字体修改混乱
    vs远程调试
    nuget pack 时不包含依赖包(而不是引用项目的dll,区别于IncludeReferencedProjects)
    Inno Setup入门(二十二)——Inno Setup类参考(8)
    学习GitHub
    python3.4读取excel数据绘图
  • 原文地址:https://www.cnblogs.com/DiZhang/p/12544846.html
Copyright © 2011-2022 走看看