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("错误信息")
原文地址:https://www.cnblogs.com/tfzz/p/12032329.html