Go语言入门第三节 Go 语言面向对象机制

Go语言面向对象编程

Go语言的面相对象和主流语言有很大的不同,如Go 语言里是不支持继承,Go语言的接口实现也不太一样

1. 数据和行为的封装数据的封装定义一个结构体type Employee struct { Id string Name string Age string}使用实例里的值func TestStruck (t *testing.T) { //初始化一个结构体 e := Employee{“1″,”李比”,”20″} e1 := Employee{Id:”2″,Age:”23″} //使用new关键字返回一个指向这个结构体的指针,相当于使用了取地址符”&” e2 := new(Employee) e2.Age = “30”}

PS:使用new关键字会返回结构体的指针、使用.就可以直接访问指针指向的结构体内的元素

行为的封装行为(方法)的定义在这个例子里,我们任然使用上面已经定义好了的结构体。定义一个结构体的行为只要在这个函数前面type Employee struct { Id string Name string Age string}//使用这种方法定义的行为在使用自己(this)的时候会进行值的复制func (e Employee) getString() string { return e.Id+”,”+e.Name+”,”+e.Age}//使用指针传入的话就会避免内存拷贝func (e *Employee) getStringPtr() string { return e.Id+”,”+e.Name+”,”+e.Age}2. 接口接口的定义和实现一个接口//=========接口定义==========type Programmer interface { writeCode() string}//=========接口实现==========type GoProgrammer struct { } func (g *GoProgrammer) writeCode() string { return “fmt.println(\”hello world\”)”}

可以看见,Go语言的接口实现完全没有看见依赖。实现接口的结构体只需要拥有和接口一样函数名和函数签名的函数就可以认为他实现了接口

因为接口的实现是非入侵性的,Go可以实现先定义实例,后面再去提出公共部分

接口的使用如下func TestInterface(t *testing.T) { var programmer Programmer programmer = new(GoProgrammer) t.Log(programmer.writeCode())}3. 扩展与复用

用于Go不支持继承,因此Go语言的扩展也变成了Go语言里争议最大的部分

扩展的实现方式//======父类 宠物类======type Pat struct {}func (p *Pat) speak() { fmt.Println(“…”)}func (p *Pat) speakTo(host string) { p.speak() fmt.Println(host)}//======子类 狗????=======type Dog struct { Pat //在这里声明一个“父类“,这个结构体就可以拥有父类的方法}func (d *Dog) speak() { fmt.Println(“旺!”)}//======程序入口======func TestDog(t *testing.T) { //var p Pat = new(Dog) d := new(Dog) d.speakTo(“123”) // … \n 123}

从上面的程序可以看出,即时使用了内嵌的匿名成员变量来代替继承,但是在程序入口里可以看出,这种做法没有实现向上转型和重载

4. 多态

下面是一个多态的例子

//=========接口定义==========type Programmer interface { writeCode() string}//=========接口实现==========type GoProgrammer struct {}func (g *GoProgrammer) writeCode() string { return “fmt.println(\”hello world\”)”}//======新的Programmer类型实现=====type JavaProgrammer struct {}func (j *JavaProgrammer) writeCode() string { return “System.out.println(\”hello world\”);”}//=======一个普通的方法,传入Programmer类型的数据func work(programmer Programmer) { fmt.Printf(“Type:%T,Code:%s\n”,programmer,programmer.writeCode())}//======程序入口======func TestPolymorphism(t *testing.T) { java := new(JavaProgrammer) goo := new(GoProgrammer) work(java) work(goo)}空接口interface{}可以表示任何类型(相当于java的Object或C中的void*)接口定义的规范倾向于把接口定义得越小越好,如果徐需要使用大接口,那么我们使用多个小接口组合而成,下面就是一个组合接口的事例type Interface1 interface{ …}type Intercace2 interface{ …}type BigInterface interface{ Interface1 Interface2}Go语言的异常机制

Go语言没有传统意义上的错误机制,Go 语言的创始人认为程序员对异常的使用对代码的影响会很大,他们更喜欢C一样的对返回值的判断;并且Go支持多返回值,因此可以通过多返回一个错误码来处理异常

errer接口这是一个Go语言内置的接口,只有一个方法。他的定义如下// The error built-in interface type is the conventional interface for// representing an error condition, with the nil value representing no error.type error interface { Error() string}

我们在函数里可以另外抛出一个实现上面的接口的结构体。可以使用??errors.New(“错误说明”)??的方式来快速创建一个错误类(结构体)

// 斐波纳切数列func GetFib(n int) ([]int, error) { if n<0 || n>100{ return nil,errors.New(“输入的数不符合规定”) } fibList := []int {1,1} for i:=2;i<n;i++{ fibList = append(fibList,fibList[i-2]+fibList[i-1]) } return fibList,nil}panic和recover和上面的error接口一样,他们都是Go语言提供的用于处理异常的工具。panic的调用方法是panic(interface{}),recover的调用方法是recover()panic一般用于不可恢复的错误中断程序和??os.Exit(int)??方法不同,??panic(interface{})??会调用defer指定的函数,也会输出当前调用栈的信息(相当于java的异常类被抛出)recover用于掩盖一个错误,使用recover函数会拿到panic抛出的异常,并且在defer函数里处理这个异常在使用这种异常处理机制的时候需要小心由于在异常处理块(recover)没有有效的处理异常甚至只是打印在日志里而导致自己的程序编程”僵尸进程”。有时候直接让程序抛出异常也不失为一种比较好的选择下面是一个关于panic和recover的示例(相当于Java中的try、catch)func TestError(t *testing.T) { defer func () { if err := recover();err != nil { fmt.Println(“异常被掩盖:”,err) } fmt.Println(“运行defer”) }() fmt.Println(“开始执行”) //出现不可调和的错误,终止程序 panic(errors.New(“出现异常”)) fmt.Printf(“执行结束”)}

运行结果如下

=== RUN TestError开始执行异常被掩盖: 出现异常运行defer— PASS: TestError (0.00s)PASS

【来源:国外高防服务器 stgf.html 欢迎留下您的宝贵建议】都属于昨天。哪怕那山再青,那水再秀,

Go语言入门第三节 Go 语言面向对象机制

相关文章:

你感兴趣的文章:

标签云: