繁体   English   中英

Golang 向下转换结构列表

[英]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.Pagemain.Page都将实现这一点,因为后者嵌入了前者。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM