go语言,方法,接口,异常处理

go语言·

  1,方法

  2,接口 

//方法   其实方法就是一个函数
/*
    基础知识:
        1.方法:对象绑定方法,类绑定方法
            特点:就是可以自动传值
        2,在Python中,写在类当中,没有加装饰器的,从严格意义说,如果类来调,就是一个函数,对象调,就是方法
            类来调,有几个参数就传几个参数,self要自己手动传
    go方法:
        //语法  (a Person)叫接受器称之为方法
        //func (a Person) getName()  {
        //}
        //方法是给对象用的,给结构体绑定方法
        //例如给Person结构体加一个打印名字的方法
type  Person struct {
    name string
    age int
}

//语法  (a Person)叫接受器称之为方法
//func (a Person) getName()  {
//}
//方法是给对象用的,给结构体绑定方法
//例如给Person结构体加一个打印名字的方法
func (a Person) printName()  {  //  printName()就是普通函数,有返回值就在后面加返回值类型
    fmt.Println(a.name)
}

//普通函数
func printName(a Person)  {
    fmt.Println(a.name)
}

func (a *Person) changeName(name string){
    a.name=name
    fmt.Println(a)
}
func main() {
    //p:=Person{name:"lqz"}
    //p.printName()
    ////执行函数
    //printName(p)
    //为什么已经有函数了,还要有方法?
    // 方法有了,就相当于你拿到一个百宝箱,直接可以点拿到结构体中属性,面向对象的
    // 而函数需要一个个去传去取
    
    p:=&Person{name:"lqz"}
    p.changeName( "qqq")
    fmt.Println(p)


    //值接受器与指针类型接受器
    //值接受器相当于新copy一份过去,进行改的时候改的是copy过来的,不影响原来的
    //指针接受器是地址
    //func (a Person) printName() 即func (写值) printName(),在内部修改值,不会影响外部的值
    //func (a *Person) printName() 即func (指针) printName(name string) 在内部修改值,会影响外部的//什么时候用指针接受器,什么时候用值接受器
    // 是否改变外部值和拷贝结构体的代价
}
package main

import "fmt"

//匿名字段的方法  可以提升

type Person1 struct {
    name string
    age int
    sex int
    Hobby  //匿名字段  不匿名不会提升
}

type Hobby struct {
    id int
    hobbyname string
}

func (h Hobby) printHobbyId()  { //绑定方法
    fmt.Println(h.id)
}

func (a Person1) printName()  {
    fmt.Println(a.name)
}

func (a *Person1) changeName(name string)  {
    a.name=name
    fmt.Println(a)
}

func main() {
    p:=Person1{name:"lqz",Hobby:Hobby{id:10}}
    //p.printHobbyId()
    //正常操作
    p.Hobby.printHobbyId()  //10
    //非正常操作,方法也提升了
    p.printHobbyId()   //10   用了面向对象继承的方法,自己有调自己,自己没有调父类的思想
}
package main

import "fmt"
// 在方法中使用值接受器 与 在函数中使用值接受器
// 在方法中使用指针接受器 与 在 函数中只要指针接受器
type Person2 struct {
    name string
    age int
    sex int
}
//函数中使用值作为参数
func printName1(a Person2)  {
    fmt.Println(a.name)
}
//函数中使用指针作为参数
func printName2(a *Person2)  {
    //fmt.Println((*a).name)
    //支持下面的写法
    fmt.Println(a.name)
}
//在方法中使用值接受器
func (a Person2)printName()  {
    fmt.Println(a.name)
}
// 在方法中使用指针接受器
func (a *Person2)printName2()  {
    fmt.Println(a.name)
}

func main() {
    p:=Person2{name:"kkk"}
    // 调用值接受器
    p.printName()
    // 调用指针接受器
    p.printName2()

    //调用值函数
    printName1(p)
    //调用指针函数
    printName2(&p)

    //总结:不管是值接受器还是指针接受器,都可以使用值来调用
    //      不管是值接收器还是指针接受器,都可以使用指针来调用
    //      在函数中,是什么参数,就得传什么参数
    pp:=&Person2{name:"kkkk"}
    pp.printName()
    pp.printName2()
}
非结构体上绑定方法

package main

import "fmt"

//非结构体上的方法,    (接收器可以是结构体,也可以是非结构体)
//func (i int)add()  {
//    i++
//}

//重命名 ,传统的不支持绑定方法,你可以重命名后绑定方法
type Myint int

//func (i Myint) add()  {
//    i++
//    fmt.Println(i) //11 ,但是fmt.Println(a)为10
//
//}

func (i *Myint) add()  {
    (*i)++
        fmt.Println(i)  //打印的是地址
        fmt.Println(*i) // 11
    }

func main() {
    var a Myint=10
    a.add()
    fmt.Println(a) //11
}

接口

package main

import "fmt"

//接口
/*
接口是一系列方法的集合
    语法:
        type 接口名 interface {
            方法一
            方法二
            }
*/
//定义了一个鸭子接口
type Duck interface{
    run()   //func 关键字省略, 此时该方法没有返回值,可以不写
    speak()   //runn()() 后面第一括号里为参数,第二个括号里为返回值 例如 run(a int)int
}

//实现该接口(结构体要实现接口,只要该结构体实现了接口中的所有的方法,就实现了该接口)
//侵入式接口和非侵入式接口
// java当中必须要实现的接口就是侵入式接口,必须要实现的,只要把那个接口拿掉就会报错,java,c++
// 在python和go中都是非侵入式接口,可以把接口拿掉,不会影响程序的运行,不会报错,,不会对你代码造成影响

//定义一个普通鸭子的结构体
type PDuck struct {
    name string
    age string
}

//实现run方法
func (p PDuck)run()  {
    fmt.Println("我是普通鸭子,名字叫",p.name,"走路爽歪歪")
}
//实现speak
func (p PDuck)speak()  {
    fmt.Println("我是普通鸭子,名字叫",p.name,"各个说过话")
}

//定义一个唐老鸭的结构体
type TDuck struct {
    name string
    age string
    wife bool
}

//实现run方法
func (p TDuck)run()  {
    fmt.Println("我是唐老鸭,名字叫",p.name,"走路爽歪歪")
}
//实现speak
func (p TDuck)speak()  {
    fmt.Println("我是唐老鸭,名字叫",p.name,"各个说过话")
}

func main()  {
    pD:=PDuck{name:"水鸭子"}
    tD:=TDuck{name:"唐老鸭"}
    //写一个函数让鸭子说话,不管是水鸭子,还是唐老鸭
    speak(pD)
    speak(tD)

    //定义一个鸭子类型的变量
    var d Duck   //给类型定义变量
    d = pD
    d = tD
    fmt.Println(d)   //类似于面向对象的多态,鸭子有多种形态

    // 问题研究,想在函数中拿出唐老鸭的wife属性
    speak(tD)
}


//写一个函数让鸭子说话,不管是水鸭子,还是唐老鸭
// 只能分别写,下面这种写法太麻烦,代码冗余 改进方法用
//func speak(p PDuck)  {
//    p.speak()
//}
//func speak2(t TDuck)  {
//    t.speak()
//}

//改进方法 传类型
//func speak(p Duck)  {
//    //p.speak()   //只要是同一类事物,都可以传过来
//    // 问题研究,想在函数中拿出唐老鸭的wife属性
//    //在这里拿属性
//        //就用类型断言,断言你是TDuck类型,如果没有问题,转成TDuck类型
//    a:=p.(TDuck)
//    fmt.Println(a.wife)
//    p.speak()
//}

//
func speak(p Duck)  {
    switch a:=p.(type) { //类型不确定,通过case来进行判断
    case PDuck:
        fmt.Println("你是普通鸭子")
    //    判断是普通鸭子,把普通鸭子的名字拿出来
        fmt.Println(a.name)
    case TDuck:
        //    判断是唐老鸭,把唐老鸭的wife拿出来
        fmt.Println("你是唐老鸭")
        fmt.Println(a.wife)  //在不同的类型中a是不一样的
    }
}

空接

package main
import "fmt"

//空接口(里面一个方法都没有)
// 是不是所有的类型都实现了空接口,是
//所有的类型都可以赋值给空接口
type Empty interface {
    
}
type speaks struct {
    name string
}

func main()  {
    test(1)
    test("sss")
    p:=speaks{name:"kkk"}
    test(p)
    //什么类型都支持

    test4(1)
    test4("sss")
    p1:=speaks{name:"kkkee"}
    test4(p1)

}

func test(a Empty)  {
    fmt.Println(a)
}

func test4(a interface{})  {
    switch a.(type) {
    case int:
        fmt.Println("我是int类型")
    case string:
        fmt.Println("我是字符串类型")
    default:
        fmt.Println("不知道是什么类型")
    }
}
实现多个接口

接口嵌套

接口的零值是nil类型,即接口是引用类型

猜你喜欢

转载自www.cnblogs.com/Fzhiyuan/p/12040351.html