ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 7.3\. 数据结构 我们先定义一个结构类型,用于保存数据。wiki系统由一组互联的wiki页面组成,每个wiki页面包含内容和标题。我们定义wiki页面为结构page, 如下: ``` type page struct { title string body []byte } ``` 类型[]byte表示一个byte slice。(参考Effective Go了解slices的更多信息) 成员body之所以定义为[]byte而不是string类型,是因为[]byte可以直接使用io包的功能。 结构体page描述了一个页面在内存中的存储方式。但是,如果要将数据保存到磁盘的话,还需要给page类型增加save方法: ``` func (p *page) save() os.Error { filename := p.title + ".txt" return ioutil.WriteFile(filename, p.body, 0600) } ``` 类型方法的签名可以这样解读:“save为page类型的方法,方法的调用者为page类型的指针变量p。该成员函数没有参数,返回值为os.Error,表示错误信息。” 该方法会将page结构的body部分保存到文本文件中。为了简单,我们用title作为文本文件的名字。 方法save的返回值类型为os.Error,对应WriteFile(标准库函数,将byte slice写到文件中)的返回值。通过返回os.Error值,可以判断发生错误的类型。如果没有错误,那么返回nil(指针、接口和其他一些类型的零值)。 WriteFile的第三个参数为八进制的0600,表示仅当前用户拥有新创建文件的读写权限。(参考Unix手册 open(2) ) 下面的函数加载一个页面: ``` func loadPage(title string) *page { filename := title + ".txt" body, _ := ioutil.ReadFile(filename) return &page{title: title, body: body} } ``` 函数loadPage根据页面标题从对应文件读取页面的内容,并且构造一个新的 page变量——对应一个页面。 go中函数(以及成员方法)可以返回多个值。标准库中的io.ReadFile在返回[]byte的同时还返回os.Error类型的错误信息。前面的代码中我们用下划线“_”丢弃了错误信息。 但是ReadFile可能会发生错误,例如请求的文件不存在。因此,我们给函数的返回值增加一个错误信息。 ``` func loadPage(title string) (*page, os.Error) { filename := title + ".txt" body, err := ioutil.ReadFile(filename) if err != nil { return nil, err } return &page{title: title, body: body}, nil } ``` 现在调用者可以检测第二个返回值,如果为nil就表示成功装载页面。否则,调用者可以得到一个os.Error对象。(关于错误的更多信息可以参考os package documentation) 现在,我们有了一个简单的数据结构,可以保存到文件中,或者从文件加载。我们创建一个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,并且将p2的值打印到 屏幕。 可以用类似以下命令编译运行程序: ``` $ 8g wiki.go $ 8l wiki.8 $ ./8.out This is a sample page. ``` (命令8g和8l对应GOARCH=386。如果是amd64系统,可以用6g和6l) 点击这里查看我们当前的代码。