我希望能够不那么严格地解组yaml文件。也就是说,我的库具有yaml文件必须具有的预定义数量的选项。然后,用户应该能够扩展它以包括任何自定义选项。
这就是我所拥有的
package main
import (
"net/http"
"yamlcms"
"github.com/julienschmidt/httprouter"
)
type Page struct {
*yamlcms.Page
Title string
Date string
}
func getBlogRoutes() {
pages := []*Page{}
yamlcms.ReadDir("html", pages)
}
// This section is a work in progress, I only include it for loose context
func main() {
router := httprouter.New()
//blogRoutes := getBlogRoutes()
//for _, blogRoute := range *blogRoutes {
// router.Handle(blogRoute.Method, blogRoute.Pattern,
// func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {})
//}
http.ListenAndServe(":8080", router)
}
这是yamlcms包:
package yamlcms
import (
"io/ioutil"
"os"
"strings"
"gopkg.in/yaml.v2"
)
type Page struct {
Slug string `yaml:"slug"`
File string `yaml:"file"`
}
func (page *Page) ReadFile(file string) (err error) {
fileContents, err := ioutil.ReadFile(file)
if err != nil {
return
}
err = yaml.Unmarshal(fileContents, &page)
return
}
func isYamlFile(fileInfo os.FileInfo) bool {
return !fileInfo.IsDir() && strings.HasSuffix(fileInfo.Name(), ".yaml")
}
func ReadDir(dir string, pages []*Page) (err error) {
filesInfo, err := ioutil.ReadDir(dir)
if err != nil {
return
}
for i, fileInfo := range filesInfo {
if isYamlFile(fileInfo) {
pages[i].ReadFile(fileInfo.Name())
}
}
return
}
这里有一个编译器问题:
src/main.go:19: cannot use pages (type []*Page) as type []*yamlcms.Page in argument to yamlcms.ReadDir
我在这个问题上的主要目的是学习在Go中做这种事情的惯用方法。其他第三方解决方案可能存在,但我不会立即对它们感兴趣,因为我经常在Go中与遗传等有关。所以按照我所提出的方式,我怎么能最好(惯用)完成我的目标?
编辑:
所以我按照建议进行了一些更改。现在我有了这个:
type FileReader interface {
ReadFile(file string) error
}
func ReadDir(dir string, pages []*FileReader) (err error) {
filesInfo, err := ioutil.ReadDir(dir)
if err != nil {
return
}
for i, fileInfo := range filesInfo {
if isYamlFile(fileInfo) {
(*pages[i]).ReadFile(fileInfo.Name())
}
}
return
}
但是,我仍然遇到类似的编译器错误:
src/main.go:19: cannot use pages (type []*Page) as type []*yamlcms.FileReader in argument to yamlcms.ReadDir
即使main.Page应该是FileReader,因为它嵌入了yamlcms.Page。
答案 0 :(得分:1)
编辑:我忘记了切片界面不能那样工作。您需要分配一个新切片,将所有页面转换为FileReaders
,调用该函数并将其转换回来。
另一种可能的解决方案是重构yamlcms.ReadDir
以返回文件的内容,以便以后可以解组它们:
// In yamlcms.
func ReadYAMLFilesInDir(dir string) ([][]byte, error) { ... }
// In client code.
files := yamlcms.ReadYAMLFilesInDir("dir")
for i := range pages {
if err := yaml.Unmarshal(files[i], &pages[i]); err != nil { return err }
}
原始答案:
Go中没有继承或强制转换等内容。更喜欢设计中的构图和界面。在您的情况下,您可以重新定义yamlcms.ReadDir
以接受界面FileReader
。
type FileReader interface {
ReadFile(file string) error
}
yamlcms.Page
和main.Page
都会实现这一点,因为后者会嵌入前者。