zoukankan      html  css  js  c++  java
  • 12-方法

    方法

    什么是方法

    方法其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。(我们也可以这么理解,结构体是一系列属性的集合,方法和结构体写一块类似于python中的类。)

    语法

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

    Type是结构体(接收器),methodName是方法名。

    方法示例   (下面两个示例,一个是对方法没有传参的,一个是传参之后修改nam值的)

    package main
    import "fmt"
    //结构体
    type Person struct {
        name string
        age int
        sex int
    }
    //创建一个方法:给Person结构体一个打印名字的方法
    func (a Person)printName()  {
        fmt.Println(a.name)       //bb
    }
    //创建一个方法:传入一个参数name,修改name值
    func (a Person)changeName(name string)  {
        a.name=name
        fmt.Println(a)         //{jj 0 0}
    }
    
    func main() {
        p:=Person{name:"bb"}  //给结构体赋值
        p.printName()  //调用方法printName获取name值
        p1:=Person{name:"xxx"}
        p1.changeName("jj")  //传参,调用方法changeName修改name值
        fmt.Println(p1)       //{xxx 0 0}
    }

    方法中结构体是指针的情况:

    package main
    import "fmt"
    //结构体
    type Person struct {
        name string
        age int
        sex int
    }
    
    //创建一个方法:结构体是指针情况下,修改name值
    func (a *Person)changeName1(name string)  {
        a.name=name
        fmt.Println(*a)
    }
    
    func main() {
        var p2 =&Person{name:"zzz"}   //试验不加&也行
        p2.changeName1("kkk")
    }
    #结果
    {kkk 0 0}

    为什么已经有函数了还需要方法呢?

    package main
    import (
        "fmt"
    )
    
    type Employee struct {
        name     string
        salary   int
        currency string
    }
    
    /*
    displaySalary()方法被转化为一个函数,把 Employee 当做参数传入。
    */
    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 不是纯粹的面向对象编程语言,而且Go不支持类。因此,基于类型的方法是一种实现和类相似行为的途径。
    • 相同的名字的方法可以定义在不同的类型上,而相同名字的函数是不被允许的(******)。假设我们有一个 Square 和 Circle 结构体。可以在 Square 和 Circle 上分别定义一个 Area 方法。见下面的程序。
    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())
    }

    什么时候使用指针接收器,什么时候使用值接收器

    package main
    
    import "fmt"
    //结构体
    type Person struct {
        name string
        age int
        sex int
    }
    
    //创建一个方法:值接收器
    func (a Person)changeName(name string)  {
        a.name=name
    }
    
    //创建一个方法:指针接收器
    func (a *Person)changeAge(age int)  {
        a.age=age
    }
    
    func main() {
        p:=Person{name:"xxx",age:20}
        fmt.Println(p.name)       //xxx
        p.changeName("jj") 
        fmt.Println(p.name)       //xxx
    
        fmt.Println(p.age)       //20
        p.changeAge(10)
        fmt.Println(p.age)      //10
    }

    指针接收器与值接收器

    func (值接收器)changeName(name string):在内部修改值,不会影响外部的值
    func (指针接收器)changeAge(age int):在内部修改值,会影响外部的值

    那什么时候使用指针接收器,什么什么时候使用值接收器当你想修改原值的时候就用指针接收器

    匿名字段的方法

    package main
    import (
        "fmt"
    )
    
    type address struct {
        city  string
        state string
    }
    
    func (a address) fullAddress() {
        fmt.Printf("Full address: %s, %s", a.city, a.state)
    }
    
    type person struct {
        firstName string
        lastName  string
        address
    }
    
    func main() {
        p := person{
            firstName: "Elon",
            lastName:  "Musk",
            address: address {
                city:  "Los Angeles",
                state: "California",
            },
        }
    
        p.fullAddress() //访问 address 结构体的 fullAddress 方法
    }

    在上面程序的第 32 行,我们通过使用 p.fullAddress() 来访问 address 结构体的 fullAddress() 方法。明确的调用 p.address.fullAddress() 是没有必要的。该程序输出:

    Full address: Los Angeles, California

    在方法中使用值接收器和在函数中使用值参数

    在方法中使用指针接收器和在函数中使用指针参数

    package main
    import "fmt"
    
    type Person2 struct {
        name string
        age int
        sex int
    }
    //方法中使用值接收器
    func (a Person2)printName()  {
        fmt.Println(a.name)
    
    }
    //方法中使用指针接收器
    func (a *Person2)printName2()  {
        fmt.Println(a.name)
    }
    //函数中使用值参数
    func printName(a Person2)  {
        fmt.Println(a.name)
    }
    //在函数中使用指针参数
    func printName2(a *Person2)  {
        fmt.Println(a.name)
    }
    
    func main() {
        p:=&Person2{name:"lqz"}
        //调用值接收器
        p.printName()
        //调用指针接收器
        p.printName2()
        //调用值函数
        printName(p)
        //调用指针函数
        printName2(&p)
        //不管是指针接收器还是值接收器,都可以使用值来调用
        //不管是指针接收器还是值接收器,都可以使用指针来调用
        //函数中,是什么参数,就得传什么参数
    
    }

    在非结构体上的方法

    package main
    import "fmt"
    
    //重命名
    type MyInt int
    
    
    func (i *MyInt)add()  {
        (*i)++
        fmt.Println(*i)
    }
    
    func main() {
        var a MyInt=10
        a.add()
        fmt.Println(a)
    }
  • 相关阅读:
    PLSQL配置介绍
    jquery实现无外边框table
    以太坊白皮书
    区块链技术教程,如何从零开始学习以太坊及区块链
    Python机器学习中文版
    史上最全TensorFlow学习资源汇总
    什么是人工智能?终于说明白了
    Python 语音识别
    Step by Step 真正从零开始,TensorFlow详细安装入门图文教程!帮你完成那个最难的从0到1
    什么是加密经济学? 初学者终极指南
  • 原文地址:https://www.cnblogs.com/wangcuican/p/12031619.html
Copyright © 2011-2022 走看看