Linux → ChromeOS → Android → Эмулятор Linux

«С какой стати вы купили Chromebook для веб-разработки?» - это вопрос, который мне иногда задают. Люди, кажется, не верят, что я могу научиться полноценной веб-разработке на машине, которая продается за ее простоту и удобство в использовании.

Признаюсь, когда я купил вещь перед Рождеством, я не ожидал от нее никаких чудес. Поскольку он поставлялся с текстовым редактором и интернет-браузером, я видел в нем дешевый портативный способ изучения основ интерфейсной веб-разработки и просмотра YouTube на ходу. Мне также нравилась концепция «облачных вычислений» (за этим будущее).

Как оказалось, я был приятно удивлен тем, насколько способна эта маленькая машинка. Он загружается смехотворно быстро, имеет отличное время автономной работы и с помощью вездесущего «облака» делает почти все, что вы ожидаете от любой другой машины. Кроме того, в выбранной мной модели есть сенсорный экран, который можно складывать в различные позы для йоги, чтобы вы могли получить планшет, «палатку» или любую другую конфигурацию, которая вам нравится, которая, во всяком случае, выглядит круто.

Однако в последние пару недель я стал больше интересоваться серверной разработкой (отчасти мотивированной бурными отношениями между мной и CSS). Я читал о том, как можно установить Ubuntu Linux на Chromebook (если я правильно понимаю, сама ChromeOS в основном построена на базовом ядре Linux). Я еще мог бы это сделать, но, похоже, это немного сложный процесс, который требует переключения в режим разработчика, стирает локальное хранилище и отключает все приятные функции безопасности, которыми славится ChromeOS. Решил поискать альтернативу.

И я нашел тот, который работает на удивление хорошо. Видите ли, Google недавно представил приложения Android для некоторых моделей Chromebook - и, помимо некоторых проблем с дизайном / пользовательским интерфейсом, все, что работает на вашем телефоне Android, должно работать без сбоев в ChromeOS. Одно из таких приложений, которые я установил, - Termux - эмулятор Linux для Android, не требующий рутирования. Я играл с ним последние несколько дней, и достаточно сказать, я очень впечатлен. Фредрик Форнуолл проделал невероятную работу.

Я начал с пары статей, написанных Орельеном Жиро - и бац! До того, как я допил утренний кофе, у меня был запущен сервер Node.js и база данных NeDB на моем Chromebook локально - никакого страшного режима разработчика не требовалось! Если у вас есть устройство Android, я настоятельно рекомендую добавить в закладки учебник Орелиен и попробовать его. На вашем телефоне будет запущен сервер Node.js за считанные минуты.

Теперь у меня все в порядке с Node, но мне также интересно попробовать несколько других серверных языков - чтобы посмотреть, какие есть варианты, прежде чем сузить круг и выбрать один, на котором нужно сосредоточиться. Один язык, о котором я читал, - это Go, представленный Google еще в 2009 году. В последнее время он работает хорошо, и его популярность растет - фактически, он был назван языком программирования 2016 года.

Go в некоторых отношениях похож на такие языки, как C и C ++, и на его дизайн действительно повлияли они. Однако основной мотивацией для создания Go в первую очередь была неприязнь к сложности этих давно установленных языков. В результате Go намеренно стал гораздо более простым в использовании языком.

Насколько проще?

Например, в Go нет цикла while. Нет, когда дело доходит до циклов, у вас есть один и только один вариант: цикл for.

//basically a 'while' loop:
for i < 1000 {
   //something
   i++
}

Вывод типа не является обязательным. Вы можете объявить и инициализировать переменную долгим путем или воспользоваться ярлыком и неявно присвоить тип.

var x int = 2
//is the same as:
x := 2

Утверждения «if» и «else» довольно просты:

x := 5
if x > 10 {
   fmt.Println("Greater than 10")
} else {
     fmt.Println("Less than or equal to 10")
}

Go также быстро компилируется и поставляется со всеми видами полезных пакетов, доступных в стандартной библиотеке, которая хорошо документирована в Интернете. Он использовался в ряде проектов, в том числе в таких известных, как Google, Dropbox, Soundcloud, Twitch и Uber.

Я рассудил, что если им это подходит, то, вероятно, стоит взглянуть на него. Для всех, кто делает первые шаги в бэкенд-разработке, я составил небольшое руководство, основанное на моих экспериментах с Go с использованием Termux. Если у вас есть устройство Android или Chromebook с доступом к Play Store, установите и запустите Termux, и мы готовы к работе (EDIT: каламбур не на самом деле).

Если у вас есть обычное устройство Linux, не стесняйтесь присоединиться! Инструкции для самой серверной программы должны нормально работать на любой платформе, поддерживающей Go.

Начни с Termux

Termux, как и любое другое приложение для Android, очень просто загрузить и установить. Просто выполните поиск в Play Store и нажмите «УСТАНОВИТЬ». Когда он будет готов, откройте его. У вас должен быть красивый пустой интерфейс командной строки, оглядывающийся на вас. Я настоятельно рекомендую использовать физическую клавиатуру (встроенную, либо подключенную через micro-USB или Bluetooth), но если у вас ее нет под рукой, я слышал хорошие отзывы о другом приложении для Android под названием Hacker’s Keyboard.

Как говорилось в учебнике Орелиена за прошлый год, Termux поставляется с очень небольшим количеством предустановленных приложений. Выполните в терминале следующие команды:

$ apt update
$ apt upgrade
$ apt install coreutils

Хороший. Все обновлено, а coreutils поможет вам немного легче ориентироваться в файловой системе. Давайте проверим, где мы находимся в дереве каталогов.

$ pwd

Это должно вернуть имя пути, показывающее, где вы в данный момент находитесь в каталоге. Если нас там еще нет, давайте перейдем в «домашнюю» папку и посмотрим, что внутри:

$ cd $HOME && ls

Хорошо, давайте создадим новый каталог для нашего руководства по Go и перейдем в него. Затем мы можем создать новый файл с именем «server.go».

$ mkdir go-tutorial && cd go-tutorial
$ touch server.go

Если мы введем «ls», мы увидим этот единственный файл в нашем каталоге. А теперь давайте возьмем текстовый редактор. Учебник Орелиен знакомит вас с Vim, и если вы предпочитаете его использовать, то обязательно сделайте это. Немного более «дружественный к новичкам» редактор, который я буду использовать здесь, называется nano. Давайте установим это и откроем наш файл server.go:

$ apt install nano
$ nano server.go

Большой! Теперь мы можем начать набирать столько кода, сколько захотим. Но прежде чем мы это сделаем, давайте установим компилятор Go, потому что он нам понадобится для того, чтобы наш код был хоть сколько-нибудь полезен. Выйдите из nano, нажав Ctrl + X, и в командной строке введите:

$ apt install golang

Теперь давайте вернемся в nano и начнем писать наш серверный код!

Создание простого веб-сервера

Мы собираемся написать простую программу, которая запускает сервер и обслуживает HTML-страницу, которая позволяет пользователю ввести пароль для входа в систему и увидеть приветственное сообщение (или сообщение типа «Извините, попробуйте еще раз», если пароль неверный. ). В nano начните со следующего:

//Build a web server
package main
import (
   "fmt"
   "net/http"
)

Что мы сделали, так это создали пакет. Программы Go всегда запускаются пакетами. Это способ хранения и организации кода, который позволяет легко и просто вызывать функции из других пакетов. Фактически, это следующее, что мы написали. Мы сказали Go импортировать пакет «fmt» и пакет «http» из каталога «net» в стандартной библиотеке. Это дает нам доступ к функциям, которые позволяют нам играть с «форматированным вводом-выводом», а также с HTTP-запросами и ответами.

А теперь давайте разместим это в Интернете. Несколькими строками ниже напишем следующий код:

func main() {
   http.ListenAndServe(":8080",nil)
   fmt.Println("Server is listening at port 8080")
}

Подобно C, C ++, Java и т. Д., Программы Go вводятся с функцией «main ()». Мы приказали серверу прислушиваться к запросам на порту 8080 (хотя вы можете выбрать другой номер) и распечатать сообщение, информирующее нас о том, что он делает.

Пока хватит! Давайте сохраним файл (Ctrl + O), выйдем (Ctrl + X) и запустим нашу программу. В командной строке введите:

go run server.go

Это попросит компилятор Go скомпилировать и запустить программу. После небольшой паузы программа должна запуститься. Надеюсь, вы увидите следующий результат:

Server is listening at port 8080

Блестяще! Ваш сервер прослушивает запросы на порту 8080. К сожалению, он не знает, что делать с полученными запросами, потому что мы не сказали ему, как отвечать. Это следующий шаг. Прервите серверную программу, нажав Ctrl + C, и снова откройте server.go в nano.

Отправка ответа

Нам нужен сервер, чтобы «обрабатывать» запросы и возвращать соответствующие ответы. К счастью, импортированный нами пакет http позволяет легко это сделать.

Для удобства чтения вставим следующий код между оператором import () и функцией main (). Однако мы могли бы просто продолжить выполнение функции main (), и все было бы хорошо. Делай по-своему!

В любом случае, давайте напишем функцию-обработчик.

func handler (write http.ResponseWriter, req *http.Request) {
   fmt.Fprint(write, "<h1>Hello!</h1>")
}

Это функция, которая принимает два аргумента: write и req. Им присвоены типы ResponseWriter и * Request, которые определены в пакете «http». Затем мы просим сервер написать в ответ HTML-код.

Чтобы использовать эту функцию, нам нужно вызвать ее в функции main (). Добавьте код, выделенный полужирным шрифтом, ниже:

func main() {
   http.ListenAndServe(":8080",nil)
   fmt.Println("Server is listening at port 8080")
   http.HandleFunc("/", handler)
}

Строка, которую мы добавили, вызывает HandleFunc () из пакета http. Это требует двух аргументов. Первый - это строка, а второй относится к функции handler (), которую мы написали только что. Мы просим сервер обрабатывать все запросы к корневому веб-каталогу «/» с помощью функции handler ().

Сохраните и закройте server.go, затем из консоли снова запустите сервер.

go run server.go

Опять же, мы должны увидеть выходное сообщение, сообщающее нам, что сервер ожидает запросов. А почему бы нам не отправить запрос? Просто откройте свой веб-браузер и перейдите по адресу http: // localhost: 8080 /.

Chromebook, как правило, довольно самоуверенно относится к тому, какой браузер вам следует использовать, но я обнаружил, что Chrome несколько отказывается от сотрудничества, когда дело доходит до подключения к любым портам localhost. Эту проблему решила установка приложения Mozilla Firefox для Android из Play Store.

В качестве альтернативы, если вы хотите полностью оставаться в рамках Termux (а почему бы и нет?), Попробуйте Lynx. Это текстовый браузер, который существует с 1992 года. В нем нет изображений, CSS и, конечно, JavaScript. Однако для целей этого руководства он отлично справляется со своей задачей. Установить и запустить с помощью:

$ apt install lynx
$ lynx localhost:8080

Если все в порядке, в выбранном вами браузере вы должны увидеть заголовок «Привет!» Если нет, вернитесь в nano и просмотрите server.go. Ошибки, которые я сделал в первый раз, включали фигурные скобки {} вместо скобок для оператора import (). Также было несколько случайных запятых, маскирующихся под точки (возможно, мне следует использовать Ctrl + Alt + ’+’, чтобы увеличить размер шрифта в Termux).

Самый эксклюзивный веб-сайт в мире

Теперь наш сервер отвечает на HTTP-запросы красивой короткой строкой HTML. Не совсем следующий Facebook, но на шаг ближе, чем мы были раньше. Давайте сделаем это немного интереснее.

Напомним, что мы собираемся создать страницу, которая запрашивает у пользователя пароль. Если пароль неверен, пользователь получает предупреждающее сообщение. Если это правильно, то пользователь получает большое сообщение с надписью «Добро пожаловать!» Поскольку это ваш собственный сервер на вашем компьютере, и только вы знаете пароль, это будет очень эксклюзивный веб-сайт.

Во-первых, давайте сделаем HTML-ответ немного интереснее. Вернитесь к функции handler(), которую мы написали ранее. Вставьте весь код, выделенный полужирным шрифтом, вместо того, что уже есть (это всего одна строка). Осторожно с кавычками! Я начал и заканчивал строку двойными кавычками и использовал одинарные кавычки в разделе HTML. Убедитесь, что вы последовательны.

func handler (write http.ResponseWriter, req *http.Request) {
   fmt.Fprint(write, "<h1>Login</h1><form action='/log-in/' method='POST'> Password:<br> <input type='password' name='pass'><br> <input type='submit' value='Go!'></form>")
}

Когда мы запускаем сервер, HTML должен отобразить следующую страницу:

Теперь я понимаю, что здесь я предполагаю немного познакомиться с HTML. Вкратце, у нас есть заголовок и форма. Атрибут «действие» формы называется «/ log-in /», а его метод установлен на POST. Есть два поля ввода: одно для ввода пароля, а другое для отправки формы. Поле пароля называется «пройти». Нам понадобится ссылаться на эти имена позже.

Итак, что произойдет, если мы введем пароль и отправим его? Итак, мы делаем еще один HTTP-запрос («/ log-in /») к серверу, поэтому нам нужно написать другую функцию, которая обрабатывает этот запрос. Вернитесь в Termux и откройте server.go в любом текстовом редакторе.

Мы собираемся создать еще одну функцию (лично я бы написал ее между handler () и main (), но делаю все, что вам подходит). Это еще одна функция для обработки HTTP-запросов - на этот раз для запросов «/ log-in /», которые выполняются всякий раз, когда пользователь отправляет форму, которую мы создали ранее.

func loginHandler (write http.ResponseWriter, req *http.Request){
   password := req.FormValue("pass")
   if password == "let-me-in" {
                fmt.Fprint(write, "<h1>Welcome!</h1>")
   } else {
         fmt.Fprint(write, "<h3>Wrong password! Try again.</h3>")
   }
}

Как и раньше, эта функция имеет два аргумента, write и req, которым назначаются те же типы, что и в пакете «http».

Затем мы создаем переменную с именем пароль, которую устанавливаем равной «значению» поля ввода формы запроса, называемому «pass». Обратите внимание на неявное присвоение типа с использованием «: =»? Мы можем это сделать, потому что значение поля пароля всегда будет отправляться в виде строки.

Далее идет инструкция «if», в которой используется оператор сравнения «==», чтобы проверить, совпадает ли пароль со строкой «let-me-in». Конечно, именно так мы и определяем правильный пароль. Вы можете изменить эту строку на все, что захотите.

Если строки идентичны идентичны, вы в деле! А пока мы печатаем скучное «приветственное» сообщение. Мы изменим это через минуту.

В противном случае, если строки не идентичны, мы распечатываем сообщение «попробуйте еще раз». Опять же, мы могли бы сделать это немного интереснее. Для начала было бы полезно, если бы форма пароля все еще была доступна пользователю. Добавьте следующий код, выделенный полужирным шрифтом. Все это тот же пароль в формате HTML, что и раньше.

func loginHandler (write http.ResponseWriter, req *http.Request){
password := req.FormValue("pass")
if password == "let-me-in" {
                fmt.Fprint(write, "<h1>Welcome!</h1>")
} else {
         fmt.Fprint(write, "<h1>Login</h1><form action='/log-in/' method='POST'> Password:<br> <input type='password' name='pass'><br> <input type='submit' value='Go!'></form><h3 style='color: white; background-color: red'>Wrong password! Try again.</h3>")
   }
}

Я также добавил простой стиль к сообщению «попробуйте еще раз». Совершенно необязательно, но почему бы и нет? Сделаем то же самое с приветственным сообщением:

func loginHandler (write http.ResponseWriter, req *http.Request){
password := req.FormValue("pass")
if password == "let-me-in" {
                fmt.Fprint(write, "<h1 style='color: white; background-color: navy; font-size: 72px'>Welcome!</h1>")
} else {
         fmt.Fprint(write, "<h1>Login</h1><form action='/log-in/' method='POST'> Password:<br> <input type='password' name='pass'><br> <input type='submit' value='Go!'></form><h3 style='color: white; background-color: red'>Wrong password! Try again.</h3>")
   }
}

Почти готово! Мы написали нашу функцию loginHandler (), но в нашей функции main () нет ссылки на нее. Добавьте следующую полужирную строку кода:

func main() {
   http.ListenAndServe(":8080",nil)
   fmt.Println("Server is listening at port 8080")
   http.HandleFunc("/", handler)
   http.HandleFunc("/log-in/", loginHandler)
}

Там! Теперь мы сказали серверу, что если он получает запрос «/ log-in /» (который он будет получать всякий раз, когда пользователь нажимает кнопку отправки), используйте функцию loginHandler() для ответа. Были сделаны! Весь код в server.go должен выглядеть примерно так:

//Build a web server
package main
import (
   "fmt"
   "net/http"
)
func handler (write http.ResponseWriter, req *http.Request) {
   fmt.Fprint(write, "<h1>Login</h1><form action='/log-in/' method='POST'> Password:<br> <input type='password' name='pass'><br> <input type='submit' value='Go!'></form>")
}
func loginHandler (write http.ResponseWriter, req *http.Request){
   password := req.FormValue("pass")
   if password == "let-me-in" {
                fmt.Fprint(write, "<h1 style='color: white;       background-color: navy; font-size: 72px'>Welcome!</h1>")
   } else {
         fmt.Fprint(write, "<h1>Login</h1><form action='/log-in/' method='POST'> Password:<br> <input type='password' name='pass'><br> <input type='submit' value='Go!'></form><h3 style='color: white; background-color: red'>Wrong password! Try again.</h3>")
   }
}
func main() {
   http.ListenAndServe(":8080",nil)
   fmt.Println("Server is listening at port 8080")
   http.HandleFunc("/", handler)
   http.HandleFunc("/log-in/", loginHandler)
}

Сохраните и выйдите из nano, а из командной строки попросите компилятор Go построить наш сервер. Эта команда компилирует программу один раз и позволяет нам запускать ее в любое время после этого.

go build server.go

Дайте ему пару минут на компиляцию, затем введите следующую команду:

./server

Вы должны получить обычное сообщение слушает. Теперь, если вы войдете в браузер и войдете в http: // localhost: 8080 (или какой бы номер порта вы ни выбрали), вам будет предложено ввести пароль. Если мы введем его неправильно, получим следующее:

А если ввести правильный пароль:

Заключительные замечания

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

Конечно, созданной нами простой странице входа еще предстоит пройти долгий путь, прежде чем появится что-нибудь, о чем можно было бы написать домой. На самом деле вы не стали бы записывать HTML в функции-обработчики, как мы здесь (в пакете Go в html есть несколько хороших параметров шаблонов, которые я собираюсь изучить), и вы не будете определять правильный пароль в операторе «if». Было бы гораздо лучше иметь базу паролей (и имен пользователей), которую вы запрашивали бы каждый раз, когда сервер получает запрос на вход.

С этой целью Termux предлагает пакет SQLite, а также различные пакеты баз данных, доступные в Node.js. Отличным расширением этого руководства было бы создание базы данных имен пользователей и их паролей, а также возможность добавления новых пользователей. Вы бы начали с добавления еще одного поля ввода и изменения функции loginHandler ().

Я уже высказал свое мнение о Termux - он замечательный, и я надеюсь, что он станет только лучше по мере появления новых пакетов. Помимо Go и Node.js, я успешно написал и скомпилировал / запустил простые программы на C, C ++, CoffeeScript, PHP и Python 3.6, и есть еще другие языки, на которые я еще не смотрел (кто-то в Erlang / Lua / PicoLisp?)

Что касается Go, моя первая встреча была положительной. Мне нравится его упор на простоту, и мне нравится синтаксис, и документация находится на доступном уровне, но подталкивает меня к развитию моего понимания. Что бы ни стоило относительное мнение новичка по этому поводу, это похоже на нечто среднее между C ++ и Python. В некоторой степени, вероятно, именно это и должно быть!