Есть ли способ очистить этот код 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)
}