(四) Go高级类型_2
方法
type MyClass struct { name string } func (this *MyClass) SetName( newName string ) { this.name = newName }Go 没有类。然而,仍然可以在结构体类型上定义方法。
方法接收者出现在func关键字和方法名之间的参数中。
type MyString string func (this MyString) Show() { fmt.Println(this) } func main() { myString := MyString("Hello World") myString.Show() return }也可以为包中的任意类型指定任意方法,但不能对来自其它包的类型指定方法。
接收者为指针的方法
func (this MyStruct) Show() { //接收者不为指针 } func (this *MyStruct) Show() { //接收者为指针 }方法可以与命名类型或命名类型的指针关联。
用命名类型的指针 ( this *MyStruct ) 如果值类型是大的结构体的话会更有效率。其次,方法可以修改接收者指向的值。
接口
type IShow interface { Show() } type MyString string func (this MyString) Show() { fmt.Println(this) } func main() { myString := MyString("Hello World") var myShow IShow = myString // 可以看作 IShow(myString) myShow.Show() return }接口类型是由一组方法定义的集合。
接口类型的值可以存放实现这些方法的任何值。
类型通过实现那些方法来实现接口。没有显示声明的必要;所以也就没有关键字 “implements”。
隐式接口解耦了实现接口的包和定义接口的包;互不依赖。
因此,也就无需再每一个实现上增加新的接口名称,这样同时也鼓励了明确的接口定义。
type IShow interface { Show() } type ISet interface { Set() } type MyString string func (this MyString) Show() { fmt.Println(this) } type MyInt int32 func (this MyInt) Show() { fmt.Println(this) } func (this MyInt) Set() { fmt.Println("My Int Set") } func main() { myString := MyString("Hello World") var myShow IShow = myString myShow.Show() myInt := MyInt(1) var mySet ISet = myInt mySet.Set() return }也就是说只要对应的类型(Type)实现了对应的接口(Interface)的方法,那么该接口则可以匹配这个类型。无需互相声明。
Stringers
一个普遍存在的接口是 fmt 包中定义的 Stringer (Interface)。
type Stringer interface { String() string }Stringer 是一个可以用字符串描述自己的类型。‘ fmt ’ 包(还有许多其他包)使用这个来进行输出。
当然我们自己的类型也可以实现这个接口然后来输出:
type MyClass struct { Name string Age int } func (this *MyClass) String() string { return fmt.Sprintf("Name = %s, Age = %d", this.Name, this.Age) } func main() { my := &MyClass{"QuestionMark", 1} fmt.Println(my) return } //输出:Name = QuestionMark, Age = 1
错误
Go程序使用 error 值来表示错误状态。
与 fmt.Stringer 类型, error 类型是一个内建接口:
type error interface { Error() string }(与 fmt.Stringer 类似,fmt 包在输出时也会试图匹配 error。)
通常函数会返回一个 error 值,调用的它的代码应当判断这个错误是否等于 nil,来进行错误处理。
type MyClass struct { Name string Age int } func (this *MyClass) Set(name string, age int) error { if name == "" || age == 0 { return this } this.Name = name this.Age = age return nil } func (this *MyClass) Error() string { return fmt.Sprintf("MyClass Set Error") } func main() { my := &MyClass{} err := my.Set("", 0) if err != nil { log.Fatal(err) } return }
Readers
io 包指定了 io.Reader 接口,它表示从数据流结尾读取。
Go 标准库包含了这个接口方法的多个实现,包括文件/ 网络连接/ 压缩/ 加密等等。
io.Reader 接口有一个 Read() 方法:
func (T) Read(b []byte) (n int, err error)Read 用数据填充指定的字节 slice,并且返回填充的字节数和错误信息。在遇到数据流结尾时,返回 io.EOF 错误。
如:对bytes进行Read读取(多数用于Net上)
func main() { r := bytes.NewReader([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8}) buffer := make([]byte, 1) for { n, err := r.Read(buffer) if err == io.EOF { break } fmt.Println("n : ", n, " buffer : ", buffer) } return }