diff --git a/l6/Lesson6.slide b/l6/Lesson6.slide
new file mode 100644
index 0000000..96a0ff4
--- /dev/null
+++ b/l6/Lesson6.slide
@@ -0,0 +1,182 @@
+Go Beginners Innopolis
+Занятие 6: Стандартная библиотека, Дальнейшие шаги
+12 Mar 2020
+Tags: go, innopolis
+
+Emil Sharifullin
+Senior Software Engineer, SKB Kontur
+iam@litleleprikon.me
+@litleleprikon
+
+* В прошлых сериях
+
+- Как указать название пакета?
+- Какие элемменты пакета могут быть использованы вне пакета?
+- Как создать модуль?
+- Как определить тест?
+- Как определить бенчмарк?
+- Как определить подтест в рамках теста?
+
+* Стандартная библиотека
+
+* Строки
+
+.play src/stdlib/strings/first/main.go /START/,/END/
+
+* Конверсия строк
+
+.play src/stdlib/strings/second/main.go
+
+* Ввод / Вывод
+
+.link https://habr.com/en/post/306914/
+
+Прежде чем мы перейдем к работе с файлами, нужно узнать про пакет io. Пакет io состоит из нескольких функций, но в основном, это интерфейсы, используемые в других пакетах. Два основных интерфейса — это Reader и Writer. Reader занимается чтением с помощью метода Read. Writer занимается записью с помощью метода Write. Многие функции принимают в качестве аргумента Reader или Writer. Например, пакет io содержит функцию Copy, которая копирует данные из Reader во Writer:
+
+ func Copy(dst Writer, src Reader) (written int64, err error)
+
+* Ввод / Вывод
+
+Чтобы прочитать или записать []byte или string, можно использовать структуру Buffer из пакета bytes:
+
+ var buf bytes.Buffer
+ buf.Write([]byte("test"))
+
+Buffer не требует инициализации и поддерживает интерфейсы Reader и Writer. Вы можете конвертировать его в []byte вызвав buf.Bytes(). Если нужно только читать строки, можно так же использовать функцию strings.NewReader(), которая более эффективна, чем чтение в буфер
+
+* Файлы и папки
+
+.play src/stdlib/files/first/main.go /START/,/END/
+
+* Чтение файлов
+
+.play src/stdlib/files/second/main.go
+
+* Запись файлов
+
+.play src/stdlib/files/third/main.go
+
+* Поиск в каталоге
+
+Чтобы получить содержимое каталога, мы используем тот же os.Open(), но передаём ему путь к каталогу вместо имени файла. Затем вызывается функция Readdir:
+
+.play src/stdlib/files/fourth/main.go /START/,/END/
+
+* Поиск в каталоге
+
+Иногда мы хотим рекурсивно обойти каталоги (прочитать содержимое текущего и всех вложенных каталогов). Это делается просто с помощью функции Walk, предоставляемой пакетом path/filepath:
+
+.play src/stdlib/files/fifth/main.go
+
+* Ошибки
+
+Go имеет встроенный тип для сообщений об ошибках, который мы уже рассматривали (тип error). Мы можем создать свои собственные типы сообщений об ошибках используя функцию New из пакета errors.
+
+.play src/stdlib/errors/first/main.go
+
+* Контейнеры и сортировки
+
+* Список
+
+Пакет container/list реализует двусвязный список. Структура типа данных связного списка выглядит следующим образом:
+
+.play src/stdlib/containers/list/first/main.go
+
+* Сортировка
+
+Пакет sort содержит функции для сортировки произвольных данных. Есть несколько предопределённых функций (для срезов, целочисленных значений и чисел с плавающей точкой). Вот пример, как отсортировать ваши данные:
+
+.code src/stdlib/containers/sort/first/main.go /START FIRST/,/END FIRST/
+
+* Сортировка
+
+.play src/stdlib/containers/sort/first/main.go /START SECOND/,/END SECOND/
+
+* Хэши и криптография
+
+Функция хэширования принимает набор данных и уменьшает его до фиксированного размера. Хэши используются в программировании повсеместно, начиная от поиска данных, заканчивая быстрым детектированием изменений. Хэш-функции в Go подразделяются на две категории: криптографические и некриптографические.
+
+* Хэши и криптография
+
+Некриптографические функции можно найти в пакете hash, который включает такие алгоритмы как adler32, crc32, crc64 и fnv. Вот пример использования crc32:
+
+.play src/stdlib/hashes/first/main.go
+
+Объект crc32 реализует интерфейс Writer, так что мы можем просто записать в него набор байт, как и в любой другой Writer. После записи мы вызываем Sum32(), который вернёт uint32.
+
+* Хэши и криптография
+
+Обычным применением crc32 является сравнение двух файлов. Если значение Sum32() для обоих файлов одинаковы, то, весьма вероятно (не со стопроцентной гарантией), содержимое этих файлов идентично. Если же значения отличаются, значит файлы, безусловно, разные:
+
+.code src/stdlib/hashes/second/main.go /START FIRST/,/END FIRST/
+
+* Хэши и криптография
+
+.play src/stdlib/hashes/second/main.go /START SECOND/,/END SECOND/
+
+* Серверы
+
+* TCP сервер
+
+.code src/stdlib/servers/tcp/server/main.go /^func server/,/^}/
+
+* TCP сервер
+.code src/stdlib/servers/tcp/server/main.go /^func handleServerConnection/,/^}/
+
+* TCP сервер
+.play src/stdlib/servers/tcp/server/main.go /^func main/,/^}/
+
+* TCP клиент
+.code src/stdlib/servers/tcp/client/main.go /^func client/,/^}/
+
+* TCP клиент
+
+.play src/stdlib/servers/tcp/client/main.go /^func main/,/^}/
+
+* HTTP сервер
+
+.code src/stdlib/servers/http/server/main.go /^func hello/,/^}/
+
+.play src/stdlib/servers/http/server/main.go /^func main/,/^}/
+
+* RPC сервер
+
+.code src/stdlib/servers/rpc/server/main.go /START FIRST/,/END FIRST/
+.code src/stdlib/servers/rpc/server/main.go /START SECOND/,/END SECOND/
+
+* RPC сервер
+
+.play src/stdlib/servers/rpc/server/main.go /^func main/,/^}/
+
+* RPC клиент
+
+.code src/stdlib/servers/rpc/client/main.go /^func client/,/^}/
+.play src/stdlib/servers/rpc/client/main.go /^func main/,/^}/
+
+* Аргументы командной строки
+
+.play src/stdlib/flags/first/main.go /^func main/,/^}/
+
+ go run l6/src/stdlib/flags/first/main.go -min=2 -max=5
+ min: 2, max: 5
+
+* Синхронизация
+
+Мьютекс (или взаимная блокировка) единовременно блокирует часть кода в одном потоке, а так же используется для защиты общих ресурсов из не-атомарных операций. Вот пример использования мьютекса:
+
+.play src/stdlib/mutex/first/main.go /^func main/,/^}/
+
+* Задачка
+
+Написать веб-сервис для предоставления мьютекса
+
+- Должен использоваться контекст из стандартной библиотеки
+- Должен использоваться таймаут. Если за время таймаута мьютекс взять не получилось, то возврашать 408
+- Таймаут, хост(hostname:port) должны устанавливаться через флаги(timeout, http)
+- Запросы: POST /api/v1/lock(201), DEL /api/v1/lock(200)
+
+* Решение
+
+.link https://forms.gle/b3vD8FEhc1JKkYJ29
+
+.image img/qrcode-7.svg 500 _
diff --git a/l6/img/qrcode-7.svg b/l6/img/qrcode-7.svg
new file mode 100644
index 0000000..7085daa
--- /dev/null
+++ b/l6/img/qrcode-7.svg
@@ -0,0 +1,443 @@
+
+
\ No newline at end of file
diff --git a/l6/src/stdlib/containers/list/first/main.go b/l6/src/stdlib/containers/list/first/main.go
new file mode 100644
index 0000000..9b44209
--- /dev/null
+++ b/l6/src/stdlib/containers/list/first/main.go
@@ -0,0 +1,17 @@
+package main
+
+import (
+ "container/list"
+ "fmt"
+)
+
+func main() {
+ var x list.List
+ x.PushBack(1)
+ x.PushBack(2)
+ x.PushBack(3)
+
+ for e := x.Front(); e != nil; e = e.Next() {
+ fmt.Println(e.Value.(int))
+ }
+}
diff --git a/l6/src/stdlib/containers/sort/first/main.go b/l6/src/stdlib/containers/sort/first/main.go
new file mode 100644
index 0000000..39a646a
--- /dev/null
+++ b/l6/src/stdlib/containers/sort/first/main.go
@@ -0,0 +1,38 @@
+package main
+
+import (
+ "fmt"
+ "sort"
+)
+
+// START FIRST OMIT
+type Person struct {
+ Name string
+ Age int
+}
+
+type ByName []Person
+
+func (this ByName) Len() int {
+ return len(this)
+}
+func (this ByName) Less(i, j int) bool {
+ return this[i].Name < this[j].Name
+}
+func (this ByName) Swap(i, j int) {
+ this[i], this[j] = this[j], this[i]
+}
+
+// END FIRST OMIT
+
+// START SECOND OMIT
+func main() {
+ kids := []Person{
+ {"Jill", 9},
+ {"Jack", 10},
+ }
+ sort.Sort(ByName(kids))
+ fmt.Println(kids)
+}
+
+// END SECOND OMIT
diff --git a/l6/src/stdlib/errors/first/main.go b/l6/src/stdlib/errors/first/main.go
new file mode 100644
index 0000000..327e1c2
--- /dev/null
+++ b/l6/src/stdlib/errors/first/main.go
@@ -0,0 +1,11 @@
+package main
+
+import (
+ "errors"
+ "fmt"
+)
+
+func main() {
+ err := errors.New("error message")
+ fmt.Println(err.Error())
+}
diff --git a/l6/src/stdlib/files/fifth/main.go b/l6/src/stdlib/files/fifth/main.go
new file mode 100644
index 0000000..86f7a6b
--- /dev/null
+++ b/l6/src/stdlib/files/fifth/main.go
@@ -0,0 +1,14 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+func main() {
+ filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
+ fmt.Println(path)
+ return nil
+ })
+}
diff --git a/l6/src/stdlib/files/first/main.go b/l6/src/stdlib/files/first/main.go
new file mode 100644
index 0000000..c9e1ae2
--- /dev/null
+++ b/l6/src/stdlib/files/first/main.go
@@ -0,0 +1,31 @@
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func main() {
+ // START OMIT
+ file, err := os.Open("test.txt")
+ if err != nil {
+ fmt.Println("Cannot open file")
+ }
+ defer file.Close()
+
+ // получить размер файла
+ stat, err := file.Stat()
+ if err != nil {
+ fmt.Println("Cannot get file size")
+ }
+ // чтение файла
+ bs := make([]byte, stat.Size())
+ _, err = file.Read(bs)
+ if err != nil {
+ fmt.Println("Cannot read file")
+ }
+
+ str := string(bs)
+ fmt.Println(str)
+ // END OMIT
+}
diff --git a/l6/src/stdlib/files/fourth/main.go b/l6/src/stdlib/files/fourth/main.go
new file mode 100644
index 0000000..620b8e4
--- /dev/null
+++ b/l6/src/stdlib/files/fourth/main.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func main() {
+ // START OMIT
+ dir, err := os.Open(".")
+ if err != nil {
+ fmt.Println("Cannot open directory")
+ }
+ defer dir.Close()
+
+ fileInfos, err := dir.Readdir(-1)
+ if err != nil {
+ fmt.Println("Cannot read directory")
+ }
+ for _, fi := range fileInfos {
+ fmt.Println(fi.Name())
+ }
+ // END OMIT
+}
diff --git a/l6/src/stdlib/files/second/main.go b/l6/src/stdlib/files/second/main.go
new file mode 100644
index 0000000..cc7f5bb
--- /dev/null
+++ b/l6/src/stdlib/files/second/main.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+)
+
+func main() {
+ bs, err := ioutil.ReadFile("test.txt")
+ if err != nil {
+ fmt.Println("Cannot read file")
+ }
+ str := string(bs)
+ fmt.Println(str)
+}
diff --git a/l6/src/stdlib/files/third/main.go b/l6/src/stdlib/files/third/main.go
new file mode 100644
index 0000000..489aa1b
--- /dev/null
+++ b/l6/src/stdlib/files/third/main.go
@@ -0,0 +1,16 @@
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func main() {
+ file, err := os.Create("test.txt")
+ if err != nil {
+ fmt.Println("Cannot create file")
+ }
+ defer file.Close()
+
+ file.WriteString("test")
+}
diff --git a/l6/src/stdlib/flags/first/main.go b/l6/src/stdlib/flags/first/main.go
new file mode 100644
index 0000000..68d404e
--- /dev/null
+++ b/l6/src/stdlib/flags/first/main.go
@@ -0,0 +1,16 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+)
+
+func main() {
+ var minp int
+ // Определение флагов
+ maxp := flag.Int("max", 6, "the max value")
+ flag.IntVar(&minp, "min", 1, "the min value")
+ // Парсинг
+ flag.Parse()
+ fmt.Printf("min: %d, max: %d\n", minp, *maxp)
+}
diff --git a/l6/src/stdlib/hashes/first/main.go b/l6/src/stdlib/hashes/first/main.go
new file mode 100644
index 0000000..a351f6c
--- /dev/null
+++ b/l6/src/stdlib/hashes/first/main.go
@@ -0,0 +1,13 @@
+package main
+
+import (
+ "fmt"
+ "hash/crc32"
+)
+
+func main() {
+ h := crc32.NewIEEE()
+ h.Write([]byte("test"))
+ v := h.Sum32()
+ fmt.Println(v)
+}
diff --git a/l6/src/stdlib/hashes/second/main.go b/l6/src/stdlib/hashes/second/main.go
new file mode 100644
index 0000000..668df86
--- /dev/null
+++ b/l6/src/stdlib/hashes/second/main.go
@@ -0,0 +1,36 @@
+package main
+
+import (
+ "fmt"
+ "hash/crc32"
+ "io/ioutil"
+)
+
+// START FIRST OMIT
+func getHash(filename string) (uint32, error) {
+ bs, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return 0, err
+ }
+ h := crc32.NewIEEE()
+ h.Write(bs)
+ return h.Sum32(), nil
+}
+
+// END FIRST OMIT
+
+// START SECOND OMIT
+func main() {
+ fmt.Println("Hello")
+ h1, err := getHash("test1.txt")
+ if err != nil {
+ return
+ }
+ h2, err := getHash("test2.txt")
+ if err != nil {
+ return
+ }
+ fmt.Println(h1, h2, h1 == h2)
+}
+
+// END SECOND OMIT
diff --git a/l6/src/stdlib/mutex/first/main.go b/l6/src/stdlib/mutex/first/main.go
new file mode 100644
index 0000000..a606d9e
--- /dev/null
+++ b/l6/src/stdlib/mutex/first/main.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/signal"
+ "sync"
+ "syscall"
+ "time"
+)
+
+func main() {
+ m := new(sync.Mutex)
+
+ for i := 0; i < 10; i++ {
+ go func(i int) {
+ m.Lock()
+ fmt.Println(i, "start")
+ time.Sleep(time.Second)
+ fmt.Println(i, "end")
+ m.Unlock()
+ }(i)
+ }
+
+ sigs := make(chan os.Signal, 1)
+ signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
+ <-sigs
+}
diff --git a/l6/src/stdlib/servers/http/server/main.go b/l6/src/stdlib/servers/http/server/main.go
new file mode 100644
index 0000000..2c21add
--- /dev/null
+++ b/l6/src/stdlib/servers/http/server/main.go
@@ -0,0 +1,34 @@
+package main
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const html = `
+
+
+ Hello World
+
+
+ Hello World!
+
+`
+
+func hello(res http.ResponseWriter, req *http.Request) {
+ res.Header().Set(
+ "Content-Type",
+ "text/html",
+ )
+ io.WriteString(
+ res,
+ html,
+ )
+}
+func main() {
+ fmt.Println("Listening on :9000")
+ http.HandleFunc("/hello", hello)
+ http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("."))))
+ http.ListenAndServe(":9000", nil)
+}
diff --git a/l6/src/stdlib/servers/rpc/client/main.go b/l6/src/stdlib/servers/rpc/client/main.go
new file mode 100644
index 0000000..ca22c94
--- /dev/null
+++ b/l6/src/stdlib/servers/rpc/client/main.go
@@ -0,0 +1,25 @@
+package main
+
+import (
+ "fmt"
+ "net/rpc"
+)
+
+func client() {
+ c, err := rpc.Dial("tcp", "127.0.0.1:9999")
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ var result int64
+ err = c.Call("Server.Negate", int64(999), &result)
+ if err != nil {
+ fmt.Println(err)
+ } else {
+ fmt.Println("Server.Negate(999) =", result)
+ }
+}
+
+func main() {
+ client()
+}
diff --git a/l6/src/stdlib/servers/rpc/server/main.go b/l6/src/stdlib/servers/rpc/server/main.go
new file mode 100644
index 0000000..9568822
--- /dev/null
+++ b/l6/src/stdlib/servers/rpc/server/main.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+ "fmt"
+ "net"
+ "net/rpc"
+ "os"
+ "os/signal"
+ "syscall"
+)
+
+// START FIRST OMIT
+type Server struct{}
+
+func (this *Server) Negate(i int64, reply *int64) error {
+ *reply = -i
+ return nil
+}
+
+// END FIRST OMIT
+
+// START SECOND OMIT
+func server() {
+ rpc.Register(new(Server))
+ fmt.Println("Listening on :9999")
+ ln, err := net.Listen("tcp", ":9999")
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ for {
+ c, err := ln.Accept()
+ if err != nil {
+ continue
+ }
+ go rpc.ServeConn(c)
+ }
+}
+
+// END SECOND OMIT
+
+func main() {
+ go server()
+
+ sigs := make(chan os.Signal, 1)
+ signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
+ <-sigs
+}
diff --git a/l6/src/stdlib/servers/tcp/client/main.go b/l6/src/stdlib/servers/tcp/client/main.go
new file mode 100644
index 0000000..37d5b3b
--- /dev/null
+++ b/l6/src/stdlib/servers/tcp/client/main.go
@@ -0,0 +1,30 @@
+package main
+
+import (
+ "encoding/gob"
+ "fmt"
+ "net"
+)
+
+func client() {
+ // соединиться с сервером
+ c, err := net.Dial("tcp", "127.0.0.1:9999")
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+
+ // послать сообщение
+ msg := "Hello World"
+ fmt.Println("Sending", msg)
+ err = gob.NewEncoder(c).Encode(msg)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ c.Close()
+}
+
+func main() {
+ client()
+}
diff --git a/l6/src/stdlib/servers/tcp/server/main.go b/l6/src/stdlib/servers/tcp/server/main.go
new file mode 100644
index 0000000..0e355d4
--- /dev/null
+++ b/l6/src/stdlib/servers/tcp/server/main.go
@@ -0,0 +1,51 @@
+package main
+
+import (
+ "encoding/gob"
+ "fmt"
+ "net"
+ "os"
+ "os/signal"
+ "syscall"
+)
+
+func server() {
+ // слушать порт
+ ln, err := net.Listen("tcp", ":9999")
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ fmt.Println("Listening on :9999")
+ for {
+ // принятие соединения
+ c, err := ln.Accept()
+ if err != nil {
+ fmt.Println(err)
+ continue
+ }
+ // обработка соединения
+ go handleServerConnection(c)
+ }
+}
+
+func handleServerConnection(c net.Conn) {
+ // получение сообщения
+ var msg string
+ err := gob.NewDecoder(c).Decode(&msg)
+ if err != nil {
+ fmt.Println(err)
+ } else {
+ fmt.Println("Received", msg)
+ }
+
+ c.Close()
+}
+
+func main() {
+ go server()
+
+ sigs := make(chan os.Signal, 1)
+ signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
+ <-sigs
+}
diff --git a/l6/src/stdlib/strings/first/main.go b/l6/src/stdlib/strings/first/main.go
new file mode 100644
index 0000000..b83e968
--- /dev/null
+++ b/l6/src/stdlib/strings/first/main.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+ "fmt"
+ "strings"
+)
+
+func main() {
+ // START OMIT
+ // true
+ fmt.Println(strings.Contains("test", "es"))
+ // 2
+ fmt.Println(strings.Count("test", "t"))
+ // true
+ fmt.Println(strings.HasPrefix("test", "te"))
+ // true
+ fmt.Println(strings.HasSuffix("test", "st"))
+ // 1
+ fmt.Println(strings.Index("test", "e"))
+ // "a-b"
+ fmt.Println(strings.Join([]string{"a", "b"}, "-"))
+ // == "aaaaa"
+ fmt.Println(strings.Repeat("a", 5))
+ // "bbaa"
+ fmt.Println(strings.Replace("aaaa", "a", "b", 2))
+ // []string{"a","b","c","d","e"}
+ fmt.Println(strings.Split("a-b-c-d-e", "-"))
+ // "test"
+ fmt.Println(strings.ToLower("TEST"))
+ // "TEST"
+ fmt.Println(strings.ToUpper("test"))
+ // END OMIT
+}
diff --git a/l6/src/stdlib/strings/second/main.go b/l6/src/stdlib/strings/second/main.go
new file mode 100644
index 0000000..3945442
--- /dev/null
+++ b/l6/src/stdlib/strings/second/main.go
@@ -0,0 +1,9 @@
+package main
+
+import "fmt"
+
+func main() {
+ arr := []byte("test")
+ str := string([]byte{'t', 'e', 's', 't'})
+ fmt.Println(arr, str)
+}