• GO语言 方法 接口 异常处理


    方法

    1.什么是方法

    方法其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。

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

    2.方法的定义使用

    1.方法绑定给结构体
    //1.定义结构体
    type Person struct {
        name string
        age int
        sex int
    }
    //2.给Person结构体加一个打印名字的方法
    func (a Person)printName()  {
        fmt.Println(a.name) //接收器直接使用结构体内属性
    }
    //3.main函数中使用
    var p *Person=&Person{name:"lqz"} //实例化
    p.printName() //调用方法

    3.指针接收器和值接收器

    1.值接收器和指针接收器的区别在于方法接收器的类型;
    func (a Person)changeName(name string) //值接收器
    unc (a *Person)changeName(name string) //指针接收器
    2.
    //func (值)changeName(name string):在内部修改值,不会影响外部的值
    //func (指针)changeName(name string):在内部修改值,会影响外部的值

    示例:

    1.值接收器方法
    //1.定义结构体
    type Person struct {
       name string
       age int
       sex int
    }
    //2.绑定方法
    func (a Person)changeName(name string) {  
                               a.name=name 
                                fmt.Println(a) //{egon 0 0}
    }
    //3.main函数调用
    p.changeName("egon")
    fmt.Println(p) //{lqz 0 0}
    
    2.指针接收器方法
    //1.定义结构体
    type Person struct {
       name string
       age int
       sex int
    }
    //2.绑定方法
    func (a *Person)changeName(name string)  {
        a.name=name
        fmt.Println(a) //&{egon 0 0}
    }
    //3.main函数调用
    
        //var p *Person=&Person{name:"lqz"}
        //这种也可以,go给你处理了
            var p Person=Person{name:"lqz"}
        p.changeName("egon")
        fmt.Println(p)//{egon 0 0}

    4.匿名字段提升方法

    前提:属于结构体的匿名字段的方法可以被直接调用,就好像这些方法是属于定义了匿名字段的结构体一样。匿名才会提升不匿名不会提升。如果子类有就用自己的,没有用父类的

    1.定义
    type Person1 struct {
        name string
        age int
        sex int
        Hobby
    }
    
    type Hobby struct {
        id int
        hobbyname string
    }
    2.绑定方法
    func (h Hobby)printHobbyId()  {
        fmt.Println(h.id)
    }
    
    func (a Person1)printName()  {
        fmt.Println(a.name)
    }
    func (a Person1)printHobbyId()  {
        fmt.Println("我重写了")
        //重用父类的方法
        //a.Hobby.printHobbyId()
        fmt.Println(a.Hobby.id)
    }
    3.main函数中
        //p:=Person1{name:"lqz",Hobby:Hobby{id:10}}
        //
        ////正常操作
        ////p.Hobby.printHobbyId()
        ////非正常操作  方法也提升了
        //p.printHobbyId()

    5.补充

    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)
        //不管是指针接收器还是值接收器,都可以使用值来调用
        //不管是指针接收器还是值接收器,都可以使用指针来调用
        //函数中,是什么参数,就得传什么参数

    接口

    1.什么是接口

    接口是一系列方法的集合。

    2.接口定义和类型及零值

    1.
    type 接口名 interface{
        方法一
        方法二
    }
    2.接口类型:接口名
    3.接口零值:nil

    3.定义接口使用和类型断言

    1.第一步
    //1.定义了一个鸭子接口
    type Duck interface {
        run()
        speak()
    }
    //2.第二不:定义普通鸭子结构体
    type PDuck struct {
        name string
        age string
    }
    
    func (p PDuck)run()  {
        fmt.Println("我是普通鸭子,我名字叫",p.name,"我走路歪歪扭扭")
    }
    func (p PDuck)speak()  {
        fmt.Println("我是普通鸭子,我名字叫",p.name,"我嘎嘎说话")
    }
    
    //定义一个唐老鸭,实现鸭子接口
    type TDuck struct {
        name string
        age string
        wife bool
    }
    
    func (p TDuck)run()  {
        fmt.Println("我是普通鸭子,我名字叫",p.name,"我走路歪歪扭扭")
    }
    func (p TDuck)speak()  {
        fmt.Println("我是普通鸭子,我名字叫",p.name,"我嘎嘎说话")
    }
    //3.第三步:main函数中使用
        pD:=PDuck{name:"水鸭子"}
        tD:=TDuck{name:"唐老鸭"}
        speak(pD)
        speak(tD)
    //4.第四步:main函数外,p为接口Duck为接口类型即接口名但可以通过结构体对象 
    func speak(p Duck){
            p.speak() 
    }
    //5.类型断言主要是为了判断结构体对象是否是某个结构体类型
    方式1提前知道类型:
    func speak(p Duck)  {
    // 类型断言,我断言你是TDuck类型,如果没有问题,转成TDuck类型,然后获取属性值
     a:=p.(TDuck)
     fmt.Println(a.wife)
     p.speak()
    }
    方式2提前不知道类型:
    func speak(p Duck)  {
       switch a:=p.(type) {
       case PDuck:
          //判断好了,你是普通鸭子,把鸭子名字拿出来
          fmt.Println("你是普通鸭子")
          fmt.Println(a.name)
       case TDuck:
          //判断好了,你是唐老鸭,把唐老鸭的wife拿出来
          fmt.Println("你是唐老鸭")
    
          fmt.Println(a.wife)
       }
    }

    4.空接口和匿名空接口

    1.什么是空接口和匿名空接口

    1.没有方法的接口叫做空接口
    2.没有名字和方法的接口叫做匿名空接口
    3.这2者可以接受任意的数据类型

    2.示例

    package main
    import "fmt"
    //空接口(一个方法都没有)
    //匿名空接口
    //所有的数据类型都实现了空接口
    type Empty interface {
    
    }
    type TDuck2 struct {
        name string
        age string
        wife bool
    }
    func main() {
        test(1)
        test("ssss")
        test(TDuck2{})
        test(10.45)
        var a Empty =1
        var b Empty ="dddd"
    
    
    }
    
    //func test(a Empty)  {
    //    fmt.Println(a)
    //}
    
    func test(a interface{})  {
        switch a.(type) {
        case int:
            fmt.Println("你是int类型")
        case string:
            fmt.Println("你是string ")
        case TDuck2:
            fmt.Println("你是唐老鸭")
        default:
            fmt.Println("我不知道你是什么类型")
    
        }
    }

    5.多接口

    1.什么是多接口

    指的是一个结构体绑定多个方法,且这些方法属于不同的接口

    2.示例:

    //接口1
    type SalaryCalculator interface {
        DisplaySalary()
    }
    //接口2
    type LeaveCalculator interface {
        CalculateLeavesLeft() int
    }
    //定义结构体
    type Employee struct {
        firstName string
        lastName string
        basicPay int
        pf int
        totalLeaves int
        leavesTaken int
    }
    
    //结构体绑定方法且方法属于不同的接口
    func (e Employee) DisplaySalary() {
        fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf))
    }
    
    func (e Employee) CalculateLeavesLeft() int {
        return e.totalLeaves - e.leavesTaken
    }
    
    //main函数使用
        e := Employee {
            firstName: "Naveen",
            lastName: "Ramanathan",
            basicPay: 5000,
            pf: 200,
            totalLeaves: 30,
            leavesTaken: 5,
        }
    
        var s SalaryCalculator = e //var 变量名 接口名 = 结构体对象
        s.DisplaySalary()
        var l LeaveCalculator = e

    6.接口的嵌套

    type SalaryCalculator interface {
        DisplaySalary()
    }
    
    type LeaveCalculator interface {
        CalculateLeavesLeft() int
    }
    
    type EmployeeOperations interface {
        SalaryCalculator
        LeaveCalculator
    }

    异常处理

    1.常用方法

    defer  panic  recover
    1.defer :延迟调用(同等级所有程序执行完之后在执行,多个defer时,从下往上执行),即便程序出现错误,也会立马执行
    2.panic  就是python中的raise(主动抛出异常)
    3.recover :检测到程序出现错误时,恢复程序,继续执行

    2.异常处理模板

    1.语法:
        defer func() {
            if a:=recover();a!=nil{
                //a 如果不等于nil,表示程序出了异常,a 就是异常信息
                //a 等于nil,表示没有异常
                //fmt.Println("出错了")
                fmt.Println(a)
            }
            //用于会被执行(相当于finally)
                      fmt.Println("永远都会执行")
    
        }()
    
    2.示例:
    func f2()  {
        defer func() {
            if a:=recover();a!=nil{
                //a 如果不等于nil,表示程序出了异常,a 就是异常信息
                //a 等于nil,表示没有异常
                //fmt.Println("出错了")
                fmt.Println(a)
            }
            //用于会被执行(相当于finally)
    
        }()

    错误

    1.第一种方式不处理

    import (
        "errors"
        "fmt"
    )
    
    //1.调用:注意其中一个变量是来接收错误信息的
            a,err:=circleArea(-10)
    //处理错误信息
        if err!=nil{
            fmt.Println(err)
        }
        //fmt.Println(err)
        fmt.Println(a)//2.语法:errors.New("错误信息")
    func circleArea(radius int) (int, error) {
        if radius < 0 {
            return 0, errors.New("错误信息")
            //panic("xddd")
        }
        return 100, nil
    }

    2.主动抛出错误(不建议使用)

    panic("错误信息")
  • 相关阅读:
    POJ2186(有向图缩点)
    POJ3352(连通分量缩点)
    POJ1523(割点所确定的连用分量数目,tarjan算法原理理解)
    POJ3694(求割边)
    POJ3177(无向图变双连通图)
    POJ1144(割点入门题)
    maven(1)-linux环境下安装maven
    linux(10)-linux环境下jdk配置自定义环境变量/etc/profile.d以及卸载自带openjdk
    ant(1)-linux环境下安装ant
    apache(2)-linux环境下apache-httpd编译安装
  • 原文地址:https://www.cnblogs.com/tfzz/p/12032329.html
Copyright © 2020-2023  润新知