Go语言方法应用 go语言该怎么学?

    /    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)

分享至