【问题标题】:Is there a way of cleaning up this Go code?有没有办法清理这个 Go 代码?
【发布时间】:2012-09-19 06:43:38
【问题描述】:

我刚开始学习 Go,并且做了一个函数,它可以解析带有标头的 markdown 文件,其中包含一些元数据(这些文件是博客文章)。

这是一个例子:

---
Some title goes here
19 September 2012
---
This is some content, read it.

我写了这个函数,它可以工作,但我觉得它很冗长和混乱,我看过各种字符串包,但我对 Go 的了解不够,最好知道什么是最佳实践我应该做不同的事情,如果我能得到一些提示来清理它,我将不胜感激。 (另外,我知道我不应该忽视这个错误)。

type Post struct {
    Title string
    Date string
    Body string
}
func loadPost(title string) *Post {
    filename := title + ".md"
    file, _ := ioutil.ReadFile("posts/" + filename)
    fileString := string(file)
    str := strings.Split(fileString, "---")
    meta := strings.Split(str[1], "\n")
    title = meta[1]
    date := meta[2]
    body := str[2]
    return &Post{Title: title, Date: date, Body: body}
}

【问题讨论】:

  • 附注:blackfriday 是一个完整的 Markdown 原生 Go 解析器。
  • 谢谢,我一直在使用不同的 md 解析器 (github.com/hoisie/mustache),但 blackfriday 看起来更精致一些。
  • 不要忽略来自ioutil.ReadFile的错误!退回、记录或恐慌 - 忽略它会导致以后难以调试问题。

标签: coding-style refactoring go


【解决方案1】:

我觉得还不错。几个建议:

  • “posts/”中的硬编码斜杠取决于平台。您可以使用 path/filepath.Join 来避免这种情况。
  • 有 bytes.Split,所以不需要字符串(文件)。
  • 您无需重复字段即可创建帖子:&Post{title, date, body}

或者,您可以找出正文以LastIndex(s, "--") 开头的位置,并使用它来相应地索引文件内容。这样就避免了使用Split的分配。

const sep = "--"

func loadPost(content string) *Post {
    sepLength := len(sep)

    i := strings.LastIndex(content, sep)
    headers := content[sepLength:i]
    body := content[i+sepLength+1:]

    meta := strings.Split(headers, "\n")

    return &Post{meta[1], meta[2], body}
}

【讨论】:

  • 我不认为LastIndex 在这里有用,因为它非常贪婪。文中可能出现更多---。但是 +1 用于拆分从解析内容中读取的文件。
【解决方案2】:

我同意这还不错。我将添加一些其他想法。

  • 正如 Thomas 所示,您不需要中间变量 title date 和 body。试试吧,

    return &Post{
        Title: meta[1],
        Date: meta[2],
        Body: body,
    }
    

    确实可以省略字段名称,但我有时希望它们保持代码自记录。 (我认为 go vet 也喜欢它们。)

  • 我对字符串和字节片比较大惊小怪,但可能比我应该做的要多。由于您一口气读取文件,因此您可能无需担心这一点。将所有内容转换为一个大字符串,然后将字符串切片是一种方便的处理方式,只要记住,如果您保留其中的任何部分,您就是将整个字符串固定在内存中。如果你的文件很大或者你有很多文件,而你最终只保留了大多数文件的元数据,那么这可能不是要走的路。

  • 每个文件只有一个博客条目?如果是这样,我想我会提出托马斯建议的变体。验证第一个字节是 ---(或您的文件已损坏),然后使用 strings.Index(fileString[3:], "---")。当您有未知数量的段时,拆分更合适。在您的情况下,您只是在元数据之后寻找那个单一的分隔符。索引会在搜索元后找到它并完成,而不是搜索整个身体。 (无论如何,如果正文包含字符串“---”怎么办?)

  • 最后,有些人会为此使用正则表达式。我还没有热身正则表达式,但无论如何,这是另一种方法。

【讨论】:

    【解决方案3】:

    索尼娅有一些很棒的建议。以下是我在解析标头时可能遇到的问题。

    http://play.golang.org/p/w-XYyhPj9n

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    const sep = "---"
    
    type parseError struct {
        msg string
    }
    
    func (e *parseError) Error() string {
        return e.msg
    }
    
    func parse(s string) (header []string, content string, err error) {
        if !strings.HasPrefix(s, sep) {
            return header, content, &parseError{"content does not start with `---`!"}
        }
        arr := strings.SplitN(s, sep, 3)
        if len(arr) < 3 {
            return header, content, &parseError{"header was not terminated with `---`!"}
        }
        header = strings.Split(strings.TrimSpace(arr[1]), "\n")
        content = strings.TrimSpace(arr[2])
        return header, content, nil
    }
    
    func main() {
    
        //
        f := `---
    Some title goes here
    19 September 2012
    ---
    This is some content, read it. --Anonymous`
    
        header, content, err := parse(f)
        if err != nil {
            panic(err)
        }
    
        for i, val := range header {
            fmt.Println(i, val)
        }
        fmt.Println("---")
        fmt.Println(content)
    
        //
        f = `---
    Some title goes here
    19 September 2012
    This is some content, read it.`
    
        _, _, err = parse(f)
        fmt.Println("Error:", err)
    
        //
        f = `
    Some title goes here
    19 September 2012
    ---
    This is some content, read it.`
    
        _, _, err = parse(f)
        fmt.Println("Error:", err)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      • 2019-12-11
      • 1970-01-01
      相关资源
      最近更新 更多