2-я часть истории, которая началась с смс-ки от Кати «Не звони и не пиши мне больше!!!!»
Первая часть тут. Для тех, кому лень читать, приведу краткое изложение:
4,5 года назад я имел неосторожность начать писать свою криптовалюту на совсем неподходящем для этого дела языке — на PHP. В итоге, конечно, написал (я упрямый), но получился костыль на костыле и то, что оно вообще работало было просто какой-то магией.
Сразу хочу предупредить, программер я самоучка-недоучка и пишу код, мягко сказать, неидеально.
Началось всё с того, что я расстался с девушкой, по имени Катя и в этот же день (4 апреля 2015-го) решил изучить Go и переписать свою криптовалюту. Для тех, кому интересно, что там с Катей, я сделал спойлеры, ну а кому не интересно, просто не обращайте внимание на Катю
Поздний вечер, я уверен, что Катя останется на ночь. Но она почему-то стала твердить, что ей надо домой. Я сказал, что хочу накормить её завтраком в постели. Договорись, что завтра утром она приедет завтракать. Вызвал такси, она уехала. Уснул счастливым, т.к. нашел себе красивую девушку, с которой весело и интересно. На следующий день от неё пришла смс-ка «Привет. Чем занимаешься?». Помню свои ощущения, ведь мне написала девушка, которая мне очень нравится, это было кайфово. И скоро мы с ней должны были снова встретиться…
В тот день мы так и не встретились. И на следующий тоже. Я не знаю, что у неё происходило в голове, но она постоянно переносила свидания. Даже не поздравила с 23 февраля.
Решил её как-то растормошить. Написал Кате смс-ку: «скоро буду, конечно захвачу»
Она ответила: «в смысле?»
Я: «упс, не туда»
Она: «вот значит как»
У неё включилась ревность. Через день предложил встретиться, она согласилась.
Проанализировав её поведение и, немного погуглив, я наткнулся на книгу «Новые правила. Секреты успешных отношений для современных девушек»
За вечер прочитал и понял, что она меня зачем-то в себя влюбляет, используя советы из этой книжки.
Итог 8 месяцев: приложение работает на Win (64/32), OSX(64/32), Linux(64/32), FreeBSD(64/32), Android, IOS (будет круто, если кто-то закинет в App Store).
Общего кода ~73к строк, кода под разные ОС где-то несколько сотен строчек.
40к — обработка/генерация блоков/тр-ий, 17.5к — контроллеры для интерфейса, 15.5к — шаблоны
Поддерживаются PostgreSQL, SQLite, MySQL.
Тех, кто будет тестировать мое творение, предупреждаю — могут быть баги, и если у Вас есть время, чиркните о них, пожалуйста, на darwin@dcoin.club или в личку на хабре. Пожелания и советы тоже приветствуются.
В первой части я рассказал про то, как в dcoin функционирует веб-сервер.
В этой статье опишу, как я использую html/template
Шаблоны
Для генерации html-страниц в Go есть очень удобный пакет — html/template. Проще всего понять, как он работает, можно поэкспериментировав вот с этим примером. Как правило, шаблоны хранятся в отдельных html-файлах, но в примерах на play.golang.org, для наглядности, шаблоны вставлены в go-код.
Большую часть информации по шаблонам я получил с gohugo.io/templates/go-templates
Шаблоны у меня лежат тут. Каждый шаблон начинается с определения его имени {{ define «templateName» }}, а заканчивается {{end}}
Контроллеры, которые использует шаблоны получают html код через функцию makeTemplate. В неё я передаю название html-файла, имя шаблона (которое в {{define}} указано), параметры.
TemplateStr, err := makeTemplate("template_name", "templateName", &tplPage{
Alert: c.Alert,
Lang: c.Lang,
TxType: txType,
TxTypeId: txTypeId})
Полученный в TemplateStr набор байт передается content.go и в итоге браузер получает сформированную html-страничку
В makeTemplate для всех шаблонов я подключаю дополнительные шаблоны, такие как signatures.html, alert_success.html. А также, добавляю пользовательские функции (FuncMap), которые используются для обработки данных в шаблонах.
Мне не давал покоя вопрос о книге, по которой она, как мне казалось, влюбляет меня в себя. Спросить прямо я не решился. Поинтересовался, чего читает. Она назвала каких-то авторов. На вопрос о книгах про психологию, ответила, что почитывает для себя.
Было холодно. Проводил до дома. Договорились на днях пойти на каток.
Включения в шаблоны
Чтобы включить в шаблон другой шаблон нужно использовать такую конструкцию {{ template «signatures». }}. Точка в конце говорит о том, что нужно обработать все параметры в шаблоне signatures, без точки параметры не будут обработаны. signatures я добавляю практически во все шаблоны, вот пример
Параметры
Сравнение. Приведу сразу несколько примеров, чтобы показать, как всё просто:
{{if not .UserID}} <span>Пусто</span> {{end}}
{{if .UserID}} <span>Не пусто</span> {{end}}
{{if eq .UserID 0}} <span>UserID == 0</span> {{end}}
{{if ne .UserID 0}} <span>UserID != 0</span> {{end}}
{{if lt .UserID 0}} <span>UserID < 0</span> {{end}}
{{if le .UserID 0}} <span>UserID <= 0</span> {{end}}
{{if gt .UserID 0}} <span>UserID > 0</span> {{end}}
{{if ge .UserID 0}} <span>UserID >= 0</span> {{end}}
{{.Lang.pool} — Lang — это карта. Т.е. через точку мы получаем значение, у которого ключ «pool»
В итоге сдался. Написал ей, позвал в кино. Она сказала, что сегодня не может, т.к. переезжает. От помощи с переездом отказалась.
Забегу немного вперед и скажу, что после той самой смс-ки «Не звони и не пиши мне больше!!!!», я в ВК переманил на свою сторону её подружку, с которой она жила 2 года, чтобы та помогала мне вернуть Катю. Так вот, её подружка, сказала, что всю ту неделю, когда я не звонил, Катя очень переживала и ждала звонка от меня. Еще она рассказала, что после первого свидания Катя буквально светилась от радости. Также она добавила, что никакую книгу по соблазнению она не читала.
Пользовательские функции
html-код в переменных нужно дизэскейпить. Для этого необходимо добавить функцию:
funcMap := template.FuncMap{
"noescape": func(s string) template.HTML {
return template.HTML(s)
},
}
Все пользовательские функции у меня собраны в makeTemplate. Использовать так:
{{noescape .Lang.htmlText}}
Купил её любимые цветы, вино и пр. Хотел весь день провести с ней, но к обеду она была еще не готова, через час тоже и через два. К моему удивлению, к шести часам она, наконец, собралась. Я вызвал ей такси.
Range
Чтобы разобрать какую-нибудь карту используется Range. Вот пример, взятый отсюда:
{{range $k, $country := .Countries}}
<option value='{{$k}}' {{if eq $k $.MyCountry}} selected {{end}}>{{$country}}</option>
{{end}}
Из кода, наверное, понятно, что происходит. Но хочу обратить особое внимание на $.MyCountry. Если не добавить $, тогда доступа к параметру .MyCountry не будет. Я по началу очень часто об этом забывал и долго думал, что не так. За пределами range доступ к MyCountry снова получается через {{.MyCountry}}
Переменные
В шаблонах можно создавать свои переменные. Вот пример, взятый отсюда:
{{range $i, $pageType := .PagesArray}}
{{$counter := ""}}
{{if eq $pageType "funders"}}
{{$counter := " <span class='count h6 bg-grey-dark white'>{{$.ProjectCountFunders}}</span>"}}
{{else if eq $pageType "comments"}}
{{$counter := " <span class='count h6 bg-grey-dark white'>{{$.ProjectCountComments}}</span>"}}
{{end}}
{{$counter}}
{{end}}
В данном примере создается новая переменная $counter, которой присваивается значение, в зависимости от условия, и ниже выводится ее результат
and/or
Несколько непривычной для меня оказалась логика работы and/or.
Примеры:
{{if and (eq .Start 1) (ne .BlockId 1) (gt .UserId 0)}}
Если .Start == 1 и .BlockId != 1 и .UserId > 0
{{if or (eq .Start 1) (ne .BlockId 1) (gt .UserId 0)}}
Если .Start == 1 или .BlockId != 1 или .UserId > 0
JS-код
Еще одна проблема отняла у меня довольно много времени. Если в контроллере нужно сформировать какой-то js-код, например:
var x="1";
То при выводе его в шаблоне через {{.SomeJSCode}} мы получим
"var x="1";"
Решение 1
noescape тут не поможет. Нужно добавить новую пользовательскую функцию:
"js": func(s string) template.JS {
return template.JS(s)
},
И в шаблоне использовать {{js .SomeJSCode}}
Решение 2
В контроллере использовать тип template.JS. Предварительно преобразовав переменную string: template.JS(SomeJsStringVariable). В самом шаблоне в таком случае нужно выводить {{.SomeJSCode}}
Продолжение в следующей части.
Заключение
В следующих статьях я расскажу про БД, плавное завершение приложения через сигналы, обработку блоков из блокчейна, шифрование в GO и расшифровку в JS, про то, как я, немного изменил gomobile, добавив уведомления и работу в фоне для IOS и Android приложений.
Автор: c-darwin