Skip to content

Latest commit

 

History

History
70 lines (59 loc) · 3.69 KB

File metadata and controls

70 lines (59 loc) · 3.69 KB

让我们从定义数据结构开始。一个wiki拥有一系列相互关联的页面,每个页面有一个标题和一个体(页面内容)。这里,我们定义Page为一个带有两个用来表示标题和体字段的结构。

type Page struct {
    Title string
    Body  []byte
}

[]byte表示此字段为"一个字节切片"。 (See Slices: usage and internals for more on slices.) Body这个元素是[]byte切片而不是 string,因为是我们将使用的io库接受的数据类型,你将在随后的代码中看到。

Page结构描述展示了将要存储在内存中的页面数据。但是如何持久存储? 我们可以通过给Page创建save方法来实现它:

func (p *Page) save() error {
    filename := p.Title + ".txt"
    return ioutil.WriteFile(filename, p.Body, 0600)
}

这个方法的签名读为:'这是个名为save的方法,带有一个指向Page结构指针p作为接收者。不带有任何参数,且返回一个error类型的值。'

这个方法将Page结构的Body字段保存为一个文本文件。为了简单点,我们将使用Title字段作为文件名。

save方法返回一个error类型的值,因为那是WriteFile(一个将字节切片写入到文件的标准库函数)函数的返回类型。save方法返回这个error值,以便让应用处理当写入文件时应该发生的任何错误。如果Paged运行的没有问题。 save()将返回nil(对于指针,接口和其他一些类型来说为零值)。

这个8进制整形字面量0600,作为第3个参数传递给WriteFile,指明文件应该只给当前用户带有读写权限被创建.(See the Unix man page open(2) for details.)

除了存储页面外,我们也会想要加载页面:

func loadPage(title string) *Page {
    filename := title + ".txt"
    body, _ := ioutil.ReadFile(filename)
    return &Page{Title: title, Body: body}
}

这个loadPage通过title参数构建文件名,读取文件内容到一个新的变量体内,并返回一个指向使用合适的标题和体值构建的Page字面量的指针。

函数可以返回多个值。标准库函数io.ReadFile返回了[]byte和error。在loadPage函数中,error还没有被处理;占位符(blank identifier)使用下划线(_)符号来表示,用来丢弃error返回值(本质上,将值赋给什么也不是[nothing翻译为空不能准确表达])。

但是如果ReadFile遇到一个错误会发生什么?例如,文件可能不存在。我们不应该忽略这样的错误。让我们修改这个函数以返回*Page和error。

func loadPage(title string) (*Page, error) {
    filename := title + ".txt"
    body, err := ioutil.ReadFile(filename)
    if err != nil {
        return nil, err
    }
    return &Page{Title: title, Body: body}, nil
}

函数调用者现在可以检查第二个参数;如果它为nil那么已经成功加载了一个Page。如果不是nil,那么就是一个错误,可以被调用者处理(详细的内容请看语言规范)。

现在我们有了一个数据结构,且能够从文件中保存、加载。让我们写一个main函数来测试一下我们写了什么:

func main() {
    p1 := &Page{Title: "TestPage", Body: []byte("This is a sample Page.")}
    p1.save()
    p2, _ := loadPage("TestPage")
    fmt.Println(string(p2.Body))
}

编译和执行这个代码后,一个名为TestPage.txt的文件将被创建,包含p1变量的内容。文件将会被读到p2结构中,并且它的Body元素被打印到屏幕。

你可以像这样来编译运行程序:

$ go build wiki.go
$ ./wiki

这是个示例页。

(如果正在使用Windows,你不必在"wiki"前输入"./"来运行程序。)

点击此处查看到现在我们已经写的代码。