/ 2019-03-05
匿名字段
Go语言支持只提供类型,而不写字段名的方式,也就是匿名字段,也称为嵌入字段。
当匿名字段是一个struct的时候,那么这个struct所拥有的全部字段都被隐式地引入了当前定义的这个struct。
Go语言匿名字段可以像字段成员那样访问匿名字段方法,编译器负责查找。
package main
import "fmt"
type Student struct {
id int
name string
}
type Course struct {
Student
}
func (self *Student) ToString() string {
return fmt.Sprintf("Student: %p, %v", self, self)
}
func main() {
c := Course{Student{1, "oldboy"}}
fmt.Printf("Course: %p\n", &c)
fmt.Println(c.ToString())
}
运行结果:
Class: 0xc0420023e0
User: 0xc0420023e0, &{1 oldboy}
Go 语言不像其它面相对象语言一样可以写个类,然后在类里面写一堆方法,但其实Go语言的方法很巧妙的实现了这种效果:我们只需要在普通函数前面加个接受者(receiver,写在函数名前面的括号里面),这样编译器就知道这个函数(方法)属于哪个struct了。
继承复用
Go语言中没有继承,但是可以依靠组合来模拟继承和多态。
通过匿名字段,可获得和继承类似的复用能力。依据编译器查找次序,只需在外层定义同名方法,就可以实现。
package main
import "fmt"
type Student struct {
id int
name string
}
type Course struct {
Student
title string
}
func (self *Student) ToString() string {
return fmt.Sprintf("Student: %p, %v", self, self)
}
func (self *Course) ToString() string {
return fmt.Sprintf("Course: %p, %v", self, self)
}
func main() {
c := Course{Student{1, "oldboy"}, "Golang"}
fmt.Println(c.ToString())
fmt.Println(c.Student.ToString())
}
运行结果:
Course: 0xc04207e060, &{{1 oldboy} Golang}
Student: 0xc04207e060, &{1 oldboy}
自定义ERROR
错误是可以用字符串描述自己的任何东西。 可以由预定义的内建接口类型 error,和其返回字符串的方法 Error 构成。
type error interface {
Error() string
}
当用 fmt 包的多种不同的打印函数输出一个 error 时,会自动的调用该方法。
package main
import (
"fmt"
"os"
"time"
)
type PathError struct {
path string
op string
createTime string
message string
}
func (p *PathError) Error() string {
return fmt.Sprintf("path=%s \nop=%s \ncreateTime=%s \nmessage=%s", p.path,
p.op, p.createTime, p.message)
}
func Open(filename string) error {
file, err := os.Open(filename)
if err != nil {
return &PathError{
path: filename,
op: "read",
message: err.Error(),
createTime: fmt.Sprintf("%v", time.Now()),
}
}
defer file.Close()
return nil
}
func main() {
err := Open("/oldboy/golang.go")
switch v := err.(type) {
case *PathError:
fmt.Println("get path error,", v)
default:
}
}
(2)