Каждая задача - одна папка с соответствующим названием в папке develop, запускается через командную строку (или если не сказанно иного, из файла main.go).
-
БАЗОВАЯ ЗАДАЧА
Создать программу печатающую точное время с использованием NTP -библиотеки. Инициализировать как go module. Использовать библиотеку github.com/beevik/ntp. Написать программу печатающую текущее время / точное время с использованием этой библиотеки.
Требования:
- Программа должна быть оформлена как go module
- Программа должна корректно обрабатывать ошибки библиотеки: выводить их в STDERR и возвращать ненулевой код выхода в OS
-
ЗАДАЧА НА РАСПАКОВКУ
Создать Go-функцию, осуществляющую примитивную распаковку строки, содержащую повторяющиеся символы/руны, например:
- "a4bc2d5e" => "aaaabccddddde"
- "abcd" => "abcd"
- "45" => "" (некорректная строка)
- "" => ""
Дополнительно:
- Реализовать поддержку escape-последовательностей.
- Например:
- qwe\4\5 => qwe45 (*)
- qwe\45 => qwe44444 (*)
- qwe\\5 => qwe\\\\\ (*)
- В случае если была передана некорректная строка, функция должна возвращать ошибку. Написать unit-тесты.
-
УТИЛИТА SORT
Отсортировать строки в файле по аналогии с консольной утилитой sort (man sort — смотрим описание и основные параметры): на входе подается файл из несортированными строками, на выходе — файл с отсортированными.
Реализовать поддержку утилитой следующий ключей:
- -k — указание колонки для сортировки (слова в строке могут выступать в качестве колонок, по умолчанию разделитель — пробел)
- -n — сортировать по числовому значению
- -r — сортировать в обратном порядке
- -u — не выводить повторяющиеся строки
Дополнительно: реализовать поддержку утилитой следующих ключей:
- -M — сортировать по названию месяца
- -b — игнорировать хвостовые пробелы
- -c — проверять отсортированы ли данные
- -h — сортировать по числовому значению с учетом суффиксов
-
ПОИСК АНАГРАММ ПО СЛОВАРЮ
Написать функцию поиска всех множеств анаграмм по словарю.
Например:
- 'пятак', 'пятка' и 'тяпка' - принадлежат одному множеству,
- 'листок', 'слиток' и 'столик' - другому.
Требования:
- Входные данные для функции: ссылка на массив, каждый элемент которого - слово на русском языке в кодировке utf8
- Выходные данные: ссылка на мапу множеств анаграмм
- Ключ - первое встретившееся в словаре слово из множества. Значение - ссылка на массив, каждый элемент которого, слово из множества.
- Массив должен быть отсортирован по возрастанию.
- Множества из одного элемента не должны попасть в результат.
- Все слова должны быть приведены к нижнему регистру.
- В результате каждое слово должно встречаться только один раз.
-
УТИЛИТА GREP
Реализовать утилиту фильтрации по аналогии с консольной утилитой (man grep — смотрим описание и основные параметры).
Реализовать поддержку утилитой следующий ключей:
- -A - "after" печатать +N строк после совпадения
- -B - "before" печатать +N строк до совпадения
- -C - "context" (A+B) печатать ±N строк вокруг совпадения
- -c - "count" (количество строк)
- -i - "ignore-case" (игнорировать регистр)
- -v - "invert" (вместо совпадения, исключать)
- -F - "fixed", точное совпадение со строкой, не паттерн
- -n - "line num", напечатать номер строки
-
УТИЛИТА CUT
Реализовать утилиту аналог консольной команды cut (man cut). Утилита должна принимать строки через STDIN, разбивать по разделителю (TAB) на колонки и выводить запрошенные.
Реализовать поддержку утилитой следующий ключей:
- -f - "fields" - выбрать поля (колонки)
- -d - "delimiter" - использовать другой разделитель
- -s - "separated" - только строки с разделителем
-
OR CHANNEL
Реализовать функцию, которая будет объединять один или более done-каналов в single-канал, если один из его составляющих каналов закроется.
Очевидным вариантом решения могло бы стать выражение при использованием select, которое бы реализовывало эту связь, однако иногда неизвестно общее число done-каналов, с которыми вы работаете в рантайме. В этом случае удобнее использовать вызов единственной функции, которая, приняв на вход один или более or-каналов, реализовывала бы весь функционал.
ОПРЕДЕЛЕНИЕ ФУНКЦИИ:
var or func(channels ...<- chan interface{}) <- chan interface{}
Пример использования функции:
sig := func(after time.Duration) <- chan interface{} { c := make(chan interface{}) go func() { defer close(c) time.Sleep(after) }() return c } start := time.Now() <-or ( sig(2*time.Hour), sig(5*time.Minute), sig(1*time.Second), sig(1*time.Hour), sig(1*time.Minute), ) fmt.Printf(“fone after %v”, time.Since(start))
-
ВЗАИМОДЕЙСТВИЕ С ОС
Необходимо реализовать свой собственный UNIX-шелл-утилиту с поддержкой ряда простейших команд:
- cd <args> - смена директории (в качестве аргумента могут быть то-то и то)
- pwd - показать путь до текущего каталога
- echo <args> - вывод аргумента в STDOUT
- kill <args> - "убить" процесс, переданный в качесте аргумента (пример: такой-то пример)
- ps - выводит общую информацию по запущенным процессам в формате *такой-то формат*
Так же требуется поддерживать функционал fork/exec-команд
Дополнительно необходимо поддерживать конвейер на пайпах (linux pipes, пример cmd1 | cmd2 | .... | cmdN).
Шелл — это обычная консольная программа, которая будучи запущенной, в интерактивном сеансе выводит некое приглашение в STDOUT и ожидает ввода пользователя через STDIN. Дождавшись ввода, обрабатывает команду согласно своей логике и при необходимости выводит результат на экран. Интерактивный сеанс поддерживается до тех пор, пока не будет введена команда выхода (например \quit).
-
УТИЛИТА WGET
Реализовать утилиту wget с возможностью скачивать сайты целиком.
-
УТИЛИТА TELNET
Реализовать простейший telnet-клиент.
Примеры вызовов:
- go-telnet --timeout=10s host port
- go-telnet mysite.ru 8080
- go-telnet --timeout=3s 1.1.1.1 123
Требования:
- Программа должна подключаться к указанному хосту (ip или доменное имя + порт) по протоколу TCP. После подключения STDIN программы должен записываться в сокет, а данные полученные и сокета должны выводиться в STDOUT
- Опционально в программу можно передать таймаут на подключение к серверу (через аргумент --timeout, по умолчанию 10s)
- При нажатии Ctrl+D программа должна закрывать сокет и завершаться. Если сокет закрывается со стороны сервера, программа должна также завершаться. При подключении к несуществующему сервер, программа должна завершаться через timeout
-
HTTP-СЕРВЕР
Реализовать HTTP-сервер для работы с календарем. В рамках задания необходимо работать строго со стандартной HTTP-библиотекой.
В рамках задания необходимо:
- Реализовать вспомогательные функции для сериализации объектов доменной области в JSON.
- Реализовать вспомогательные функции для парсинга и валидации параметров методов /create_event и /update_event.
- Реализовать HTTP обработчики для каждого из методов API, используя вспомогательные функции и объекты доменной области.
- Реализовать middleware для логирования запросов.
Методы API:
- POST /create_event
- POST /update_event
- POST /delete_event
- GET /events_for_day
- GET /events_for_week
- GET /events_for_month
Параметры передаются в виде www-url-form-encoded (т.е. обычные user_id=3&date=2019-09-09). В GET методах параметры передаются через queryString, в POST через тело запроса.
В результате каждого запроса должен возвращаться JSON-документ содержащий либо {"result": "..."} в случае успешного выполнения метода, либо {"error": "..."} в случае ошибки бизнес-логики.
В рамках задачи необходимо:
- Реализовать все методы.
- Бизнес логика НЕ должна зависеть от кода HTTP сервера.
- В случае ошибки бизнес-логики сервер должен возвращать HTTP 503. В случае ошибки входных данных (невалидный int например) сервер должен возвращать HTTP 400. В случае остальных ошибок сервер должен возвращать HTTP 500.
- Web-сервер должен запускаться на порту указанном в конфиге и выводить в лог каждый обработанный запрос.
Каждый листинг - один файл с соответствующим названием в папке listing.
-
Что выведет программа? Объяснить вывод программы.
package main import ( "fmt" ) func main() { a := [5]int{76, 77, 78, 79, 80} var b []int = a[1:4] fmt.Println(b) }
-
Что выведет программа? Объяснить вывод программы. Объяснить как работают defer’ы и порядок их вызовов.
package main import ( "fmt" ) func test() (x int) { defer func() { x++ }() x = 1 return } func anotherTest() int { var x int defer func() { x++ }() x = 1 return x } func main() { fmt.Println(test()) fmt.Println(anotherTest()) }
-
Что выведет программа? Объяснить вывод программы. Объяснить внутреннее устройство интерфейсов и их отличие от пустых интерфейсов.
package main import ( "fmt" "os" ) func Foo() error { var err *os.PathError = nil return err } func main() { err := Foo() fmt.Println(err) fmt.Println(err == nil) }
-
Что выведет программа? Объяснить вывод программы.
package main func main() { ch := make(chan int) go func() { for i := 0; i < 10; i++ { ch <- i } }() for n := range ch { println(n) } }
-
Что выведет программа? Объяснить вывод программы.
package main type customError struct { msg string } func (e *customError) Error() string { return e.msg } func test() *customError { { // do something } return nil } func main() { var err error err = test() if err != nil { println("error") return } println("ok") }
-
Что выведет программа? Объяснить вывод программы. Рассказать про внутреннее устройство слайсов и что происходит при передаче их в качестве аргументов функции.
package main import ( "fmt" ) func main() { var s = []string{"1", "2", "3"} modifySlice(s) fmt.Println(s) } func modifySlice(i []string) { i[0] = "3" i = append(i, "4") i[1] = "5" i = append(i, "6") }
-
Что выведет программа? Объяснить вывод программы.
package main import ( "fmt" "math/rand" "time" ) func asChan(vs ...int) <-chan int { c := make(chan int) go func() { for _, v := range vs { c <- v time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) } close(c) }() return c } func merge(a, b <-chan int) <-chan int { c := make(chan int) go func() { for { select { case v := <-a: c <- v case v := <-b: c <- v } } }() return c } func main() { a := asChan(1, 3, 5, 7) b := asChan(2, 4 ,6, 8) c := merge(a, b ) for v := range c { fmt.Println(v) } }
Каждый паттерн - один файл с соответствующим названием в папке patterns. Тестовый запуск из файла main в папке patterns через интерактивный ввод.
- Паттерн «фасад».
- Паттерн «строитель»
- Паттерн «посетитель»
- Паттерн «комманда»
- Паттерн «цепочка вызовов»
- Паттерн «фабричный метод»
- Паттерн «стратегия»
- Паттерн «состояние»
Each task is one folder with the appropriate name in the develop folder, launched via the command line (or unless otherwise stated, from the main.go file).
-
BASIC TASK
Create a program that prints the exact time using the NTP library. Initialize as go module. Use the library github.com/beevik/ntp. Write a program that prints the current time / exact time using this library.
Requirements:
- The program must be formatted as a go module
- The program must correctly handle library errors: output them to STDERR and return a non-zero exit code to the OS
-
UNPACKING TASK
Create a Go function that performs primitive unpacking of a string containing repeated characters/runes, for example:
- "a4bc2d5e" => "aaaabccddddde"
- "abcd" => "abcd"
- "45" => "" (invalid string)
- "" => ""
Additional:
- Implement support for escape sequences.
- For example:
- qwe\4\5 => qwe45 (*)
- qwe\45 => qwe44444 (*)
- qwe\\5 => qwe\\\\\ (*)
- If an incorrect string was passed, the function should return an error. Write unit tests.
-
SORT UTILITY
Sort the lines in the file by analogy with the console utility sort (man sort - see the description and main parameters): the input is a file of unsorted lines, the output is a file with sorted lines.
Implement the utility's support for the following keys:
- -k - specifying the column to be sorted (words in a line can act as columns, the default separator is space)
- -n - sort by numeric value
- -r - sort in reverse order
- -u - do not print duplicate lines
Additional: implement the utility support for the following keys:
- -M - sort by month name
- -b - ignore trailing spaces
- -c - check if the data is sorted
- -h - sort by numeric value, taking into account suffixes
-
SEARCH FOR ANAGRAMS IN THE DICTIONARY
Write a function to search for all sets of anagrams in a dictionary.
For example:
- 'penny', 'heel' and 'chopper' - belong to the same set
- 'leaf', 'ingot' and 'table' - to another.
Requirements:
- Input data for the function: a link to an array, each element of which is a word in Russian in utf8 encoding
- Output: link to the map of sets of anagrams
- Key is the first word of a set found in the dictionary. The value is a reference to an array, each element of which is a word from the set.
- The array must be sorted in ascending order.
- Sets of one element should not be included in the result.
- All words must be converted to lowercase.
- As a result, each word should appear only once.
-
GREP UTILITY
Implement the filtering utility by analogy with the console utility (man grep - see the description and main parameters).
Implement the utility's support for the following keys:
- -A - "after" print +N lines after match
- -B - "before" print +N lines until match
- -C - "context" (A+B) print ±N lines around match
- -c - "count" (number of lines)
- -i - "ignore-case" (ignore case)
- -v - "invert" (instead of matching, exclude)
- -F - "fixed", exact match with string, not a pattern
- -n - "line num", print line number
-
CUT UTILITY
Implement a utility similar to the console command cut (man cut). The utility should receive lines via STDIN, split them by delimiter (TAB) into columns and output the requested ones.
Implement the utility's support for the following keys:
- -f - "fields" - select fields (columns)
- -d - "delimiter" - use a different delimiter
- -s - "separated" - only lines with a separator
-
OR CHANNEL
Implement a function that will combine one or more done channels into a single channel if one of its component channels closes.
The obvious solution would be to use a select expression to implement this relationship, but sometimes the total number of done channels you are working with at runtime is unknown. In this case, it is more convenient to use a call to a single function, which, having received one or more or-channels as input, would implement all the functionality.
FUNCTION DEFINITION:
var or func(channels ...<- chan interface{}) <- chan interface{}
An example of using the function:
sig := func(after time.Duration) <- chan interface{} { c := make(chan interface{}) go func() { defer close(c) time.Sleep(after) }() return c } start := time.Now() <-or ( sig(2*time.Hour), sig(5*time.Minute), sig(1*time.Second), sig(1*time.Hour), sig(1*time.Minute), ) fmt.Printf(“fone after %v”, time.Since(start))
-
INTERACTION WITH THE OS
You need to implement your own UNIX shell utility that supports a number of simple commands:
- cd <args> - change directory (the argument can be this and that)
- pwd - show the path to the current directory
- echo <args> - output the argument to STDOUT
- kill <args> - “kill” the process passed as an argument (example: such and such an example)
- ps - displays general information on running processes in the format *such and such format*
It is also required to support the functionality of fork/exec commands
Additionally, it is necessary to support the pipeline on pipes (linux pipes, example cmd1 | cmd2 | .... | cmdN).
Shell is a regular console program that, when launched, displays a certain prompt in an interactive session to STDOUT and waits for user input via STDIN. After waiting for input, it processes the command according to its logic and, if necessary, displays the result on the screen. The interactive session is maintained until a quit command (such as \quit) is issued.
-
WGET UTILITY
Implement the wget utility with the ability to download entire sites.
-
TELNET UTILITY
Implement a simple telnet client.
Call examples:
- go-telnet --timeout=10s host port
- go-telnet mysite.ru 8080
- go-telnet --timeout=3s 1.1.1.1 123
Requirements:
- The program must connect to the specified host (ip or domain name + port) via TCP. After connecting, the STDIN of the program must be written to the socket, and the data received from the socket must be output to STDOUT
- Optionally, you can pass a timeout for connecting to the server to the program (via the --timeout argument, default 10s)
- When you press Ctrl+D, the program should close the socket and exit. If the socket is closed on the server side, the program must also exit. When connecting to a non-existent server, the program must terminate after timeout
-
HTTP SERVER
Implement an HTTP server for working with a calendar. As part of the assignment, you must work strictly with the standard HTTP library.
As part of the task you must:
- Implement helper functions for serializing domain objects to JSON.
- Implement auxiliary functions for parsing and validating parameters of the /create_event and /update_event methods.
- Implement HTTP handlers for each API method using helper functions and domain objects.
- Implement middleware for request logging.
API methods:
- POST /create_event
- POST /update_event
- POST /delete_event
- GET /events_for_day
- GET /events_for_week
- GET /events_for_month
Parameters are sent in the form www-url-form-encoded (i.e. regular user_id=3&date=2019-09-09). In GET methods, parameters are passed through queryString, in POST through the request body.
As a result of each request, a JSON document must be returned containing either {"result": "..."} in case of successful execution of the method, or {"error": "..."} in case of a business logic error.
As part of the task you must:
- Implement all methods.
- Business logic should NOT depend on the HTTP server code.
- In case of a business logic error, the server must return HTTP 503. In case of an input data error (invalid int, for example), the server must return HTTP 400. In case of other errors, the server must return HTTP 500.
- The web server must run on the port specified in the config and log every processed request.
Each listing is one file with the corresponding name in the listing folder.
-
What will the program output? Explain the output of the program.
package main import( "fmt" ) func main() { a := [5]int{76, 77, 78, 79, 80} var b []int = a[1:4] fmt.Println(b) }
-
What will the program output? Explain the output of the program. Explain how defers work and the order in which they are called.
package main import ( "fmt" ) func test() (x int) { defer func() { x++ }() x = 1 return } func anotherTest() int { var x int defer func() { x++ }() x = 1 return x } func main() { fmt.Println(test()) fmt.Println(anotherTest()) }
-
What will the program output? Explain the output of the program. Explain the internal structure of interfaces and their difference from empty interfaces.
package main import ( "fmt" "os" ) func Foo() error { var err *os.PathError = nil return err } func main() { err := Foo() fmt.Println(err) fmt.Println(err == nil) }
-
What will the program output? Explain the output of the program.
package main func main() { ch := make(chan int) go func() { for i := 0; i < 10; i++ { ch <- i } }() for n := range ch { println(n) } }
-
What will the program output? Explain the output of the program.
package main type customError struct { msg string } func (e *customError) Error() string { return e.msg } func test() *customError { { //do something } return nil } func main() { var err error err = test() if err != nil { println("error") return } println("ok") }
-
What will the program output? Explain the output of the program. Tell us about the internal structure of slices and what happens when passing them as function arguments.
package main import( "fmt" ) func main() { var s = []string{"1", "2", "3"} modifySlice(s) fmt.Println(s) } func modifySlice(i []string) { i[0] = "3" i = append(i, "4") i[1] = "5" i = append(i, "6") }
-
What will the program output? Explain the output of the program.
package main import ( "fmt" "math/rand" "time" ) func asChan(vs ...int) <-chan int { c := make(chan int) go func() { for _, v := range vs { c <- v time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond) } close(c) }() return c } func merge(a, b <-chan int) <-chan int { c := make(chan int) go func() { for { select { case v := <-a: c <- v case v := <-b: c <- v } } }() return c } func main() { a := asChan(1, 3, 5, 7) b := asChan(2, 4 ,6, 8) c := merge(a, b) for v := range c { fmt.Println(v) } }
Each pattern is one file with the corresponding name in the patterns folder. Test run from the main file in the patterns folder via interactive input.
- Facade pattern
- Builder pattern
- Visitor pattern
- Command pattern
- Chain of responsibility pattern
- Factory method pattern
- Strategy pattern
- State pattern