(四) 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
}
posted @ 2017-08-16 13:58  问号是我  阅读(171)  评论(0编辑  收藏  举报