Есть ли способ очистить этот код Go?

Я только начинаю изучать Go и создал функцию, которая анализирует файлы уценки с заголовком, содержащим некоторые метаданные (файлы являются сообщениями в блоге).

вот пример:

---
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 ответа

Я думаю, что это не плохо. Пара предложений:

  • Жесткая косая черта в "posts/" зависит от платформы. Вы можете использовать путь /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}
}

Я согласен, что это не плохо. Я добавлю пару других идей.

  • Как показал Томас, вам не нужны промежуточные переменные title title и body. Попробуй хоть,

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

    Это правда, что вы можете не указывать имена полей, но иногда мне нравится, чтобы они сохраняли самодокументированный код. (Я думаю, что ветеринар любит их тоже.)

  • Я перебираю строки и байтовые фрагменты, но, вероятно, больше, чем следовало бы. Поскольку вы читаете файл одним глотком, вам, вероятно, не нужно беспокоиться об этом. Преобразование всего в одну большую строку, а затем нарезка строки - удобный способ сделать что-то, просто помните, что вы закрепляете всю строку в памяти, если сохраняете какую-либо ее часть. Если ваши файлы большие или у вас их много, и вы в конечном итоге сохраняете, скажем, мета для большинства из них, это может быть не лучшим способом.

  • Есть только одна запись в блоге на файл? Если так, я думаю, я предложу вариант предложения Томаса. Убедитесь, что первые байты --- (или ваш файл поврежден), затем используйте strings.Index(fileString[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)
}
Другие вопросы по тегам