[英]Golang downcasting list of structs
我希望能够不那么严格地解组 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 中做这种事情的惯用方式。 可能存在其他 3rd-party 解决方案,但我对它们并没有立即感兴趣,因为我在 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。
编辑:我忘记了接口片不是那样工作的。 您需要分配一个新切片,将所有页面转换为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
都将实现这一点,因为后者嵌入了前者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.