«Go»: чтение ini-файлов
Мне тут для программы на языке «Go» понадобился простой парсер
Кстати говоря, я сильно облегчил себе жизнь, когда написал небольшой
#!/bin/bash
NAME=$1
if [ -f "$NAME" ]; then
TMPNAME=`mktemp -t go.XXXXXXX`
shift
6g -I. -o $TMPNAME.6 $NAME && 6l -L. -o $TMPNAME $TMPNAME.6 && $TMPNAME $*
rm -f $TMPNAME.6 $TMPNAME >/dev/null 2>&1
else
echo "Error: '$NAME' is not found."
fiСам модуль выглядит вот так (и называется «ini»):
package ini
import (
"os"
"bufio"
"strings"
)
type inisection map[string]string
type inifile map[string]inisection
func ParseFile(name string) inifile {
f, err := os.OpenFile(name, os.O_RDONLY, 0666)
if err != nil {
return nil
}
defer f.Close()
r := bufio.NewReader(f)
one := inisection{} // одна, текущая секция
ini := inifile {} // все секции
section := "" // текущее название секции
for {
line, err := r.ReadString('\n')
if err != nil {
break
}
chunks := strings.Split(strings.TrimRight(line, "\r\n"), "=", 3)
if len(chunks) == 2 {
key, value := strings.Trim(chunks[0], "\t "), strings.Trim(chunks[1], "\t ")
last := len(value) - 1
if last > 0 && value[0] == '"' && value[last] == '"' {
value = string(value[1:last])
}
one[key] = string(value)
} else {
last := len(chunks[0]) - 1
if chunks[0][0] == '[' && chunks[0][last] == ']' {
ini[section] = one
one = inisection{}
section = string(chunks[0][1:last])
}
}
}
// «поджимаем хвост», поскольку предыдущая секция попадает в map
// только когда появляется следующая, последнюю нужно перекладывать «руками»
if len(one) > 0 {
ini[section] = one
}
return ini
}Модули пишутся очень просто — достаточно объявить как он будет называться (в директиве «package») и можно его подключать через «import». В «Go» модуль экспортирует всё, что начинается с большой буквы.
Мой модуль экспортирует единственную функцию — ParseFile, принимающую на вход имя файла, на выходе будет ассоциативный массив ассоциативных массивов (map of maps), ключами верхнего уровня является имя секции (если отсутствует, то имя пустое), ключами второго уровня — ключи
Сколько занимает программа на «Go»
Хочу немного развеять тот миф, который я невольно создал — что скомпилированные программы, написанные на языке «Go» занимают очень много. Мой скомпилированный пример
На самом деле, всё не так просто. Простенькая программа на «Go», например, классический «Hello, world!» займёт около 230КБ:
bolk-osx:Hello bolk$ cat <<GO > hello.go
> package main; func main() { println("Hello, world!") }
> GO
bolk-osx:Hello bolk$ 6g hello.go && 6l -o hello hello.6 && du -h hello
232K helloПри увеличении исходного кода размер вырастает незначительно, в моей шестимегабайтной программе большую часть занимает
Сейчас я пишу программу где уже 414 строк (в httphere — 132) и подключено 11 стандартных модулей, включая модуль для работы с изображениями («image»), скомпилированная версия занимает 1,5 мегабайта. Хотел бы попробовать сжать файл архиватором UPX, но, к сожалению, он не понимает тип запускаемых файлов моей системы