有没有办法清理这个Go代码?

时间:2012-09-19 06:43:38

标签: coding-style refactoring go

我刚刚开始学习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}
}

3 个答案:

答案 0 :(得分:4)

我认为这不错。几点建议:

  • “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}
}

答案 1 :(得分:2)

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

  • 正如Thomas所示,您不需要中间变量标题日期和正文。试试吧,

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

    确实可以将字段名称保留下来,但我有时希望它们保持代码自我记录。 (我觉得兽医也喜欢他们。)

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

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

  • 最后,有些人会使用正则表达式。我仍然没有热衷于正则表达式,但无论如何,这是另一种方法。

答案 2 :(得分:1)

索尼娅有一些很棒的建议。下面是我的看法,它解释了解析标题时可能遇到的问题。

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)
}