1
0
mirror of https://github.com/MADTeacher/go_basics.git synced 2025-11-23 21:34:47 +02:00

Переработана 5-я глава

This commit is contained in:
Stanislav Chernyshev
2025-06-14 12:40:10 +03:00
parent 17e17055d4
commit e606a539b9
84 changed files with 3247 additions and 0 deletions

16
part_5/5.1/1.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import (
"fmt"
"log"
"os"
)
func main() {
file, err := os.Create("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(file)
file.Close() // закрытие файла
}

15
part_5/5.1/10.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"fmt"
"log"
"os"
)
func main() {
data, err := os.ReadFile("pirates.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
}

25
part_5/5.1/11.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
file, err := os.Open("pirates.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}

26
part_5/5.1/12.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
file, err := os.Open("pirates.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanWords)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}

19
part_5/5.1/13.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import (
"log"
"os"
)
func main() {
firstText := "Пятнадцать человек на сундук мертвеца,\n"
secondText := "Йо-хо-хо, и бутылка рома,\n"
file, err := os.OpenFile("pirates2.txt", os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()
file.WriteString(firstText)
file.WriteString(secondText)
}

19
part_5/5.1/14.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import (
"log"
"os"
)
func main() {
firstText := "Пей, и дьявол тебя доведет до конца,\n"
secondText := "Йо-хо-хо, и бутылка рома!"
file, err := os.OpenFile("pirates2.txt", os.O_WRONLY, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()
file.WriteString(firstText)
file.WriteString(secondText)
}

22
part_5/5.1/15.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import (
"fmt"
"io"
"log"
"os"
)
func main() {
file, err := os.OpenFile("pirates2.txt", os.O_RDONLY, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()
data, err := io.ReadAll(file)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
}

34
part_5/5.1/16.go Normal file
View File

@@ -0,0 +1,34 @@
package main
import (
"fmt"
"io"
"log"
"os"
)
func main() {
originalFile, err := os.Open("pirates2.txt")
if err != nil {
log.Fatal(err)
}
defer originalFile.Close()
newFile, err := os.Create("pirates2_copy.txt")
if err != nil {
log.Fatal(err)
}
defer newFile.Close()
bytesWritten, err := io.Copy(newFile, originalFile)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Copied %d bytes", bytesWritten) // Copied 224 bytes
// Фиксируем содержимое файла и осуществляем освобождение буфера
err = newFile.Sync()
if err != nil {
log.Fatal(err)
}
}

45
part_5/5.1/17.go Normal file
View File

@@ -0,0 +1,45 @@
package main
import (
"fmt"
"log"
"os"
)
type Car struct {
model string
age uint8
weight float64
number string
}
func createCars() []Car {
return []Car{
{
model: "Oka",
weight: 13.22,
number: "ak1245j76",
age: 13,
},
{
model: "Lada7",
weight: 23.14,
number: "ak2147j175",
age: 1,
},
}
}
func main() {
myFile, err := os.Create("car_fprintln.txt")
if err != nil {
log.Fatal(err)
}
defer myFile.Close()
myCar := createCars()
for _, it := range myCar {
n, _ := fmt.Fprintln(myFile, it.model, it.number, it.age, it.weight)
fmt.Println("Записано: ", n, "байт")
}
}

46
part_5/5.1/18.go Normal file
View File

@@ -0,0 +1,46 @@
package main
import (
"fmt"
"log"
"os"
)
type Car struct {
model string
age uint8
weight float64
number string
}
func createCars() []Car {
return []Car{
{
model: "Oka",
weight: 13.22,
number: "ak1245j76",
age: 13,
},
{
model: "Lada7",
weight: 23.14,
number: "ak2147j175",
age: 1,
},
}
}
func main() {
myFile, err := os.Create("car_fprintf.txt")
if err != nil {
log.Fatal(err)
}
defer myFile.Close()
myCar := createCars()
for _, it := range myCar {
n, _ := fmt.Fprintf(myFile, "Model: %s ||Number: %s ||Age: %d ||Weight: %f\n",
it.model, it.number, it.age, it.weight)
fmt.Println("Записано: ", n, "байт")
}
}

39
part_5/5.1/19.go Normal file
View File

@@ -0,0 +1,39 @@
package main
import (
"fmt"
"io"
"log"
"os"
)
type Car struct {
model string
age uint8
weight float64
number string
}
func main() {
myFile, err := os.Open("car_fprintln.txt")
if err != nil {
log.Fatal(err)
}
defer myFile.Close()
myCars := []Car{}
for {
var car Car
n, err := fmt.Fscanln(myFile, &car.model, &car.number, &car.age, &car.weight)
if err != nil {
if err == io.EOF { // Читаем до конца файла
break
}
log.Fatal(err)
}
fmt.Println("Прочитано: ", n, "элемента(-ов)")
myCars = append(myCars, car)
}
fmt.Println(myCars)
}

19
part_5/5.1/2.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import (
"fmt"
"log"
"os"
)
func main() {
fileInfo, err := os.Stat("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("File name:", fileInfo.Name())
fmt.Println("Size in bytes:", fileInfo.Size())
fmt.Println("Permissions:", fileInfo.Mode())
fmt.Println("Last modified:", fileInfo.ModTime())
fmt.Println("Is Directory: ", fileInfo.IsDir())
}

40
part_5/5.1/20.go Normal file
View File

@@ -0,0 +1,40 @@
package main
import (
"fmt"
"io"
"log"
"os"
)
type Car struct {
model string
age uint8
weight float64
number string
}
func main() {
myFile, err := os.Open("car_fprintf.txt")
if err != nil {
log.Fatal(err)
}
defer myFile.Close()
myCars := []Car{}
for {
var car Car
n, err := fmt.Fscanf(myFile, "Model: %s ||Number: %s ||Age: %d ||Weight: %f\n",
&car.model, &car.number, &car.age, &car.weight)
if err != nil {
if err == io.EOF || err.Error() == "unexpected EOF" {
break
}
log.Fatal(err)
}
fmt.Println("Прочитано: ", n, "элемента(-ов)")
myCars = append(myCars, car)
}
fmt.Println(myCars)
}

17
part_5/5.1/3.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import (
"log"
"os"
)
func main() {
originalPath := "test.txt"
newPath := "../test2.txt" // переместит файл на уровень выше с именем test2.txt
// можно также оставить старое имя у перемещаемого файла - test.txt
// newPath := "test2.txt" // переименование файла в текущей директории
err := os.Rename(originalPath, newPath)
if err != nil {
log.Fatal(err)
}
}

14
part_5/5.1/4.go Normal file
View File

@@ -0,0 +1,14 @@
package main
import (
"log"
"os"
)
func main() {
pathToFile := "test.txt"
err := os.Remove(pathToFile)
if err != nil {
log.Fatal(err)
}
}

20
part_5/5.1/5.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import (
"fmt"
"log"
"os"
)
func main() {
pathToFile := "pirates.txt"
fileInfo, err := os.Stat(pathToFile)
if err != nil {
if os.IsNotExist(err) {
log.Fatal("File does not exist.")
os.Exit(1) // выход из приложения со статусом 1
}
}
fmt.Println("File does exist!")
fmt.Println("File information:", fileInfo)
}

23
part_5/5.1/6.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import (
"fmt"
"log"
"os"
)
func main() {
firstText := "Пятнадцать человек на сундук мертвеца,\n"
secondText := "Йо-хо-хо, и бутылка рома,"
file, err := os.Create("pirates.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// функция WriteString преобразует string в []byte, после чего записывает в файл
file.WriteString(firstText)
// ручное приведение типа string в []byte и запись данных в файл
file.Write([]byte(secondText))
fmt.Println("Text was wrote to file")
}

29
part_5/5.1/7.go Normal file
View File

@@ -0,0 +1,29 @@
package main
import (
"fmt"
"io"
"log"
"os"
)
func main() {
file, err := os.Open("pirates.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
file.WriteString("jgjgjg") // ничего в файл не добавится!!!
data := make([]byte, 128)
for {
length, err := file.Read(data)
fmt.Printf("Reading %d byte\n", length)
if err == io.EOF { // достигли конца файла?
break
}
}
fmt.Println(string(data))
fmt.Println("Text was read from file")
}

28
part_5/5.1/8.go Normal file
View File

@@ -0,0 +1,28 @@
package main
import (
"fmt"
"io"
"log"
"os"
)
func main() {
file, err := os.Open("pirates.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
tempData := make([]byte, 32)
data := []byte{}
for {
length, err := file.Read(tempData)
fmt.Printf("Reading %d byte\n", length)
if err == io.EOF { // достигли конца файла?
break
}
data = append(data, tempData...)
}
fmt.Println(string(data))
}

22
part_5/5.1/9.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
)
func main() {
file, err := os.Open("pirates.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
data, err := ioutil.ReadAll(file)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
}

15
part_5/5.2/1.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"fmt"
"log"
"os"
)
func main() {
err := os.Mkdir("myDir", 0777)
if err != nil {
log.Fatal(err)
}
fmt.Println("Directory created")
}

26
part_5/5.2/10.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"fmt"
"io/fs"
"path/filepath"
)
func main() {
countDirs := 0
countFiles := 0
filepath.WalkDir("C:\\Go", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() {
countFiles++
} else {
countDirs++
}
return nil
})
fmt.Printf("Amount of files: %d\n", countFiles)
fmt.Printf("Amount of directories: %d\n", countDirs)
}

22
part_5/5.2/11.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import (
"log"
"os"
)
func createDirWithFile() {
os.Mkdir("myDir", 0777)
myFile, err := os.Create("myDir\\test.dat")
if err != nil {
log.Fatal(err)
}
defer myFile.Close()
}
func main() {
createDirWithFile()
os.Rename("myDir", "newDir") // переименование
createDirWithFile()
os.Rename("myDir", "newDir\\myDir") // перемещение
}

18
part_5/5.2/12.go Normal file
View File

@@ -0,0 +1,18 @@
package main
import (
"fmt"
"os"
)
func main() {
pathToDir := "C:\\Go"
if _, err := os.Stat(pathToDir); os.IsNotExist(err) {
// обработка ситуации, когда директории не существует
fmt.Println("Directory isn't exist")
} else {
fmt.Println("Directory already exists")
}
}

15
part_5/5.2/2.go Normal file
View File

@@ -0,0 +1,15 @@
package main
import (
"fmt"
"log"
"os"
)
func main() {
err := os.Remove("myDir")
if err != nil {
log.Fatal(err)
}
fmt.Println("Directory removed")
}

48
part_5/5.2/3.go Normal file
View File

@@ -0,0 +1,48 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
)
const tempFileName = "myTempFile.dat"
const tempDirName = "myTempDir"
func printPath(path string, err error) string {
if err != nil {
log.Fatal(err)
}
fmt.Println("TempDir created with path: ", path)
return path
}
func createdFile(path string) {
filepath := filepath.Join(path, tempFileName)
myFile, err := os.Create(filepath)
if err != nil {
log.Fatal(err)
}
defer myFile.Close()
fmt.Println("TempFile created with path: ", filepath)
fmt.Println()
}
func main() {
os.Mkdir(tempDirName, 0777)
path := printPath(os.MkdirTemp(tempDirName, "*")) // случайное имя временного каталога
createdFile(path)
path = printPath(os.MkdirTemp(tempDirName, "temp*dir")) // имя с использованием шаблона
createdFile(path)
path = printPath(os.MkdirTemp(tempDirName, "tempdir")) // имя с использованием шаблона
createdFile(path)
// создание временного каталога со случайным именем
// в системной директории для временных файлов
path = printPath(os.MkdirTemp("", "*"))
createdFile(path)
}

62
part_5/5.2/4.go Normal file
View File

@@ -0,0 +1,62 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
)
const tempFileName = "myTempFile.dat"
const tempDirName = "myTempDir"
func printPath(path string, err error) string {
if err != nil {
log.Fatal(err)
}
fmt.Println("TempDir created with path: ", path)
return path
}
func createdFile(path string) {
filepath := filepath.Join(path, tempFileName)
myFile, err := os.Create(filepath)
if err != nil {
log.Fatal(err)
}
defer myFile.Close()
fmt.Println("TempFile created with path: ", filepath)
fmt.Println()
}
func deleteTempDir(tempDirSlice []string) {
for _, it := range tempDirSlice {
os.RemoveAll(it)
fmt.Println("TempDir with path:", it, "deleted")
}
}
func main() {
tempDirSlice := []string{}
os.Mkdir(tempDirName, 0777)
path := printPath(os.MkdirTemp(tempDirName, "*")) // случайное имя временного каталога
createdFile(path)
tempDirSlice = append(tempDirSlice, path)
path = printPath(os.MkdirTemp(tempDirName, "temp*dir")) // имя с использованием шаблона
createdFile(path)
tempDirSlice = append(tempDirSlice, path)
path = printPath(os.MkdirTemp(tempDirName, "tempdir")) // имя с использованием шаблона
createdFile(path)
tempDirSlice = append(tempDirSlice, path)
// создание временного каталога со случайным именем
// в системной директории для временных файлов
path = printPath(os.MkdirTemp("", "*"))
createdFile(path)
tempDirSlice = append(tempDirSlice, path)
deleteTempDir(tempDirSlice) // удаление всех временных каталогов
}

26
part_5/5.2/5.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
)
const tempFileName = "myTempFile.dat"
func createdFile(path string) {
filepath := filepath.Join(path, tempFileName)
myFile, err := os.Create(filepath)
if err != nil {
log.Fatal(err)
}
defer myFile.Close()
fmt.Println("File created with path: ", filepath)
}
func main() {
path := filepath.Join("firstDir", "secondDir", "new")
os.MkdirAll(path, 0777)
createdFile(path)
}

26
part_5/5.2/6.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"fmt"
"log"
"os"
"path/filepath"
)
func main() {
path := "C:\\Go" // целевая директория
files, err := os.ReadDir(path) // тип возвращаемого значения - []fs.FileInfo
if err != nil {
log.Fatal(err)
}
for _, file := range files {
if file.IsDir() {
fmt.Printf("%s is directory. Path: %v\n",
file.Name(), filepath.Join(path, file.Name()))
} else {
fmt.Printf("%s is file. Path: %v\n",
file.Name(), filepath.Join(path, file.Name()))
}
}
}

16
part_5/5.2/7.go Normal file
View File

@@ -0,0 +1,16 @@
package main
import (
"fmt"
"log"
"os"
)
func main() {
path, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
fmt.Println(path) // e:\code\golang\directory
}

27
part_5/5.2/8.go Normal file
View File

@@ -0,0 +1,27 @@
package main
import (
"fmt"
"log"
"os"
)
func getWD() {
path, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
fmt.Println("Current path:", path)
}
func main() {
getWD()
os.Mkdir("myDir", 0777)
os.Chdir("./myDir")
getWD()
myFile, err := os.Create("test.dat")
if err != nil {
log.Fatal(err)
}
defer myFile.Close()
}

21
part_5/5.2/9.go Normal file
View File

@@ -0,0 +1,21 @@
package main
import (
"fmt"
"log"
"os"
)
func getWD() {
path, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
fmt.Println("Current path:", path)
}
func main() {
getWD()
os.Chdir("../")
getWD()
}

30
part_5/5.3/1.go Normal file
View File

@@ -0,0 +1,30 @@
package main
import (
"encoding/json"
"fmt"
"log"
)
type Actor struct {
Name string
Age int
FilmsAmount int
AboutActor string
}
func main() {
actor := Actor{
Name: "Tom Hanks",
Age: 65,
FilmsAmount: 50,
AboutActor: "Tom Hanks is an actor...",
}
actorJson, err := json.Marshal(actor)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(actorJson))
}

36
part_5/5.3/2.go Normal file
View File

@@ -0,0 +1,36 @@
package main
import (
"encoding/json"
"log"
"os"
)
type Actor struct {
Name string
Age int
FilmsAmount int
AboutActor string
}
func main() {
actor := Actor{
Name: "Tom Hanks",
Age: 65,
FilmsAmount: 50,
AboutActor: "Tom Hanks is an actor...",
}
actorJson, err := json.MarshalIndent(actor, "", " ")
if err != nil {
log.Fatal(err)
}
myFile, err := os.Create("actor.json")
if err != nil {
log.Fatal(err)
}
myFile.Write(actorJson)
defer myFile.Close()
}

31
part_5/5.3/3.go Normal file
View File

@@ -0,0 +1,31 @@
package main
import (
"encoding/json"
"fmt"
"log"
"os"
)
type Actor struct {
Name string
Age int
FilmsAmount int
AboutActor string
}
func main() {
actor := &Actor{}
data, err := os.ReadFile("actor.json")
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(data, actor)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v", *actor)
}

43
part_5/5.3/4.go Normal file
View File

@@ -0,0 +1,43 @@
package main
import (
"encoding/json"
"fmt"
"log"
"os"
)
type Actor struct {
Name string
Age int
FilmsAmount int
AboutActor *string
}
func main() {
actor := &Actor{}
data, err := os.ReadFile("actor.json")
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(data, actor)
if err != nil {
log.Fatal(err)
}
// Выводим данные, прочитанные из файла
fmt.Print("Deserialized data: ")
fmt.Printf("%+v\n", *actor)
actorJson, err := json.MarshalIndent(actor, "", " ") // сериализация
if err != nil {
log.Fatal(err)
}
// Выводим сериализованные данные
fmt.Println()
fmt.Println("Serialized data:")
fmt.Println(string(actorJson))
}

33
part_5/5.3/5.go Normal file
View File

@@ -0,0 +1,33 @@
package main
import (
"encoding/json"
"fmt"
"log"
)
type Actor struct {
// имя поля при сериализации/десериализации
Name string `json:"name"`
Age int `json:"age"`
// имя тега может отличаться от имени поля структуры
FilmsAmount int `json:"films_amount"`
AboutActor *string `json:"about"`
}
func main() {
aboutStr := "Tom Hanks is an actor..."
actor := Actor{
Name: "Tom Hanks",
Age: 65,
FilmsAmount: 50,
AboutActor: &aboutStr,
}
actorJson, err := json.MarshalIndent(actor, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(actorJson))
}

33
part_5/5.3/6.go Normal file
View File

@@ -0,0 +1,33 @@
package main
import (
"encoding/json"
"fmt"
"log"
)
type Actor struct {
// имя поля при сериализации/десериализации
Name string `json:"name"`
Age int `json:"-"`
// имя тега может отличаться от имени поля структуры
FilmsAmount int `json:"-"`
AboutActor *string `json:"about"`
}
func main() {
aboutStr := "Tom Hanks is an actor..."
actor := Actor{
Name: "Tom Hanks",
Age: 65,
FilmsAmount: 50,
AboutActor: &aboutStr,
}
actorJson, err := json.MarshalIndent(actor, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(actorJson))
}

54
part_5/5.3/7.go Normal file
View File

@@ -0,0 +1,54 @@
package main
import (
"encoding/json"
"fmt"
"log"
)
type Actor struct {
// имя поля при сериализации/десериализации
Name string `json:"name"`
Age int `json:"age"`
// имя тега может отличаться от имени поля структуры
FilmsAmount int `json:"films_amount,omitempty"`
AboutActor *string `json:",omitempty"`
}
func ActorToBytes(actor Actor) []byte {
actorJson, err := json.MarshalIndent(actor, "", " ")
if err != nil {
log.Fatal(err)
}
return actorJson
}
func main() {
aboutStr := "Tom Hanks is an actor..."
// поле FilmsAmount проинициализируется значением
// по умолчанию
actor := Actor{
Name: "Tom Hanks",
Age: 65,
AboutActor: &aboutStr,
}
actorJson := ActorToBytes(actor)
// Выводим сериализованные данные
fmt.Println()
fmt.Println("First serialized data:")
fmt.Println(string(actorJson))
// поле AboutActor и Age проинициализируются значением
// по умолчанию
actor = Actor{
Name: "Tom Hanks",
FilmsAmount: 150,
}
actorJson = ActorToBytes(actor)
// Выводим сериализованные данные
fmt.Println()
fmt.Println("Second serialized data:")
fmt.Println(string(actorJson))
}

32
part_5/5.3/8.go Normal file
View File

@@ -0,0 +1,32 @@
package main
import (
"encoding/json"
"fmt"
"log"
"os"
)
type Actor struct {
// имя поля при сериализации/десериализации
Name string `json:"name"`
Age int `json:"age"`
// имя тега может отличаться от имени поля структуры
FilmsAmount int `json:"films_amount,omitempty"`
AboutActor *string `json:",omitempty"`
}
func main() {
actorJson := map[string]any{}
data, err := os.ReadFile("actor.json")
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(data, &actorJson)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v", actorJson)
}

View File

@@ -0,0 +1,3 @@
module filmography
go 1.24.3

View File

@@ -0,0 +1,8 @@
package imdb
type Actor struct {
Name string `json:"name"`
Age int `json:"age"`
FilmsAmount int `json:"filmsAmount"`
AboutActor string `json:"aboutActor"`
}

View File

@@ -0,0 +1,5 @@
package imdb
type Genre struct {
Types []string `json:"types"`
}

View File

@@ -0,0 +1,13 @@
package imdb
type Movie struct {
Name string `json:"name"`
Budget int `json:"budget"`
Actors []Actor `json:"actors"`
CriticsRating float64 `json:"criticsRating"`
AudienceRating float64 `json:"audienceRating"`
Year int `json:"year"`
Country string `json:"country"`
Genre Genre `json:"genre"`
Reviews []Review `json:"reviews"`
}

View File

@@ -0,0 +1,7 @@
package imdb
type Review struct {
Name string `json:"name"`
Text string `json:"text"`
Rating int `json:"rating"`
}

View File

@@ -0,0 +1,33 @@
package main
import (
"encoding/json"
"filmography/imdb"
"fmt"
"log"
"os"
)
func main() {
movie := &imdb.Movie{}
data, err := os.ReadFile("movie.json")
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(data, &movie)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v", movie)
// записать в файл output.json
data, err = json.MarshalIndent(movie, "", " ")
if err != nil {
log.Fatal(err)
}
err = os.WriteFile("output.json", data, 0644)
if err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,52 @@
{
"name": "Prevozmogun",
"budget": 2000000,
"actors": [
{
"name": "Alexey",
"age": 25,
"filmsAmount": 3,
"aboutActor": "2 academy awards"
},
{
"name": "Max",
"age": 33,
"filmsAmount": 2,
"aboutActor": "Very good actor"
},
{
"name": "Natalya",
"age": 18,
"filmsAmount": 1,
"aboutActor": "Rising star"
}
],
"criticsRating": 7.5,
"audienceRating": 8.5,
"year": 2019,
"country": "Russia",
"genre": {
"types": [
"Comedy",
"Drama",
"Romance"
]
},
"reviews": [
{
"name": "Igor",
"text": "I love this movie",
"rating": 10
},
{
"name": "John",
"text": "I hate this movie",
"rating": 1
},
{
"name": "Stas",
"text": "I like this movie",
"rating": 7
}
]
}

View File

@@ -0,0 +1,52 @@
{
"name": "Prevozmogun",
"budget": 2000000,
"actors": [
{
"name": "Alexey",
"age": 25,
"filmsAmount": 3,
"aboutActor": "2 academy awards"
},
{
"name": "Max",
"age": 33,
"filmsAmount": 2,
"aboutActor": "Very good actor"
},
{
"name": "Natalya",
"age": 18,
"filmsAmount": 1,
"aboutActor": "Rising star"
}
],
"criticsRating": 7.5,
"audienceRating": 8.5,
"year": 2019,
"country": "Russia",
"genre": {
"types": [
"Comedy",
"Drama",
"Romance"
]
},
"reviews": [
{
"name": "Igor",
"text": "I love this movie",
"rating": 10
},
{
"name": "John",
"text": "I hate this movie",
"rating": 1
},
{
"name": "Stas",
"text": "I like this movie",
"rating": 7
}
]
}

View File

@@ -0,0 +1,162 @@
package dotenv
import (
"bufio"
"errors"
"fmt"
"maps"
"os"
"regexp"
"strconv"
"strings"
)
type DotEnv struct {
env map[string]interface{}
}
// Регулярные выражения для int и bool
var (
intPattern = regexp.MustCompile(`^-?\d+$`)
boolPattern = regexp.MustCompile(`^(?i:true|false)$`)
)
// Создаем новый экземпляр DotEnv
// platformEnv указывает, загружать ли переменные из окружения ОС
func NewDotEnv(platformEnv bool) *DotEnv {
d := &DotEnv{env: make(map[string]interface{})}
if platformEnv {
d.env = mergeMaps(d.env, loadPlatformEnv())
}
return d
}
// Загружаем переменные из .env файлов
func (d *DotEnv) Load(paths ...string) error {
if len(paths) == 0 {
paths = []string{".env"}
}
for _, path := range paths {
file, err := os.Open(path)
if err != nil {
return fmt.Errorf(".env file not found: %s", path)
}
defer file.Close()
localEnv, err := loadLocalEnv(file)
if err != nil {
return err
}
d.env = mergeMaps(d.env, localEnv)
}
return nil
}
// Возвращает значение переменной окружения по ключу
func (d *DotEnv) GetValue(key string) (interface{}, error) {
val, ok := d.env[key]
if !ok {
return nil, fmt.Errorf("key not found: %s", key)
}
return val, nil
}
// Возвращает значение переменной окружения по ключу,
// приведенное к int. Если значение не является int,
// возвращается ошибка.
func (d *DotEnv) GetInt(key string) (int, error) {
val, ok := d.env[key]
if !ok {
return 0, fmt.Errorf("key not found: %s", key)
}
i, ok := val.(int)
if !ok {
return 0, fmt.Errorf("value for key %s is not an int", key)
}
return i, nil
}
// Возвращает значение переменной окружения по ключу,
// приведенное к bool. Если значение не является bool,
// возвращается ошибка.
func (d *DotEnv) GetBool(key string) (bool, error) {
val, ok := d.env[key]
if !ok {
return false, fmt.Errorf("key not found: %s", key)
}
b, ok := val.(bool)
if !ok {
return false, fmt.Errorf("value for key %s is not a bool", key)
}
return b, nil
}
// Возвращает значение переменной окружения по ключу,
// приведенное к string.
func (d *DotEnv) GetString(key string) (string, error) {
val, ok := d.env[key]
if !ok {
return "", fmt.Errorf("key not found: %s", key)
}
s, ok := val.(string)
if !ok {
return "", fmt.Errorf("value for key %s is not a string", key)
}
return s, nil
}
// Преобразование таблицы из переменных окружения ОС
func loadPlatformEnv() map[string]interface{} {
config := make(map[string]interface{})
for _, value := range os.Environ() {
parts := strings.SplitN(value, "=", 2)
if len(parts) != 2 {
continue
}
k := parts[0]
v := parts[1]
config[k] = parseValue(v)
}
return config
}
// Загрузка из локального .env файла
func loadLocalEnv(file *os.File) (map[string]interface{}, error) {
scanner := bufio.NewScanner(file)
config := make(map[string]interface{})
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
return nil, errors.New("invalid line in .env file: " + line)
}
key := strings.TrimSpace(parts[0])
val := strings.TrimSpace(parts[1])
config[key] = parseValue(val)
}
return config, nil
}
// Парсинг строки в int, bool или string
func parseValue(val string) interface{} {
if intPattern.MatchString(val) {
if i, err := strconv.Atoi(val); err == nil {
return i
}
}
if boolPattern.MatchString(val) {
return strings.ToLower(val) == "true"
}
return val
}
// Объединение двух map
func mergeMaps(a, b map[string]interface{}) map[string]interface{} {
maps.Copy(a, b)
return a
}

View File

@@ -0,0 +1,3 @@
module go_dotenv
go 1.24.0

View File

@@ -0,0 +1,40 @@
package main
import (
"fmt"
"go_dotenv/dotenv"
"log"
)
func main() {
env := dotenv.NewDotEnv(false)
err := env.Load(".env")
if err != nil {
log.Fatal(err)
}
adminID, err := env.GetInt("ADMIN_ID")
if err != nil {
log.Fatal(err)
}
fmt.Println(adminID)
adminPassword, err := env.GetString("ADMIN_PASSWORD")
if err != nil {
log.Fatal(err)
}
fmt.Println(adminPassword)
adminMode, err := env.GetBool("ADMIN_MODE")
if err != nil {
log.Fatal(err)
}
fmt.Println(adminMode)
adminEmail, err := env.GetString("ADMIN_EMAIL")
if err != nil {
log.Fatal(err)
}
fmt.Println(adminEmail)
}

3
part_5/5.6/my_app/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module my_app
go 1.24.0

24
part_5/5.6/my_app/main.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import (
"flag"
"fmt"
)
func main() {
// конфигурируем флаги:
// Первый аргумент - название флага
// Второй - значение по умолчанию
// Третий - описание того, что делает флаг
myStr := flag.String("str", "value", "StrFlag description")
myInt := flag.Int("int", 0, "IntFlag description")
myBool := flag.Bool("bool", false, "BoolFlag description")
// Запускаем парсинг флагов, подаваемых в командной строке
flag.Parse()
// используем флаги
fmt.Println("String flag:", *myStr)
fmt.Println("Int flag:", *myInt)
fmt.Println("Bool flag:", *myBool)
}

View File

@@ -0,0 +1,3 @@
module my_compile_app
go 1.24.0

View File

@@ -0,0 +1,12 @@
package main
import (
"fmt"
)
var VersionType = "dev"
var Version = "0.0.1"
func main() {
fmt.Printf("Version: %s (%s)\n", Version, VersionType)
}

View File

@@ -0,0 +1,6 @@
{
"debug": true,
"offset": 10,
"version": "0.0.1",
"app_name": "StaskoGo"
}

View File

@@ -0,0 +1,3 @@
module my_embed_app
go 1.24.0

View File

@@ -0,0 +1,32 @@
package main
import (
_ "embed"
"encoding/json"
"fmt"
"log"
)
//go:embed embed_config.json
var configData []byte
type Config struct {
Debug bool `json:"debug"`
Offset int `json:"offset"`
AppName string `json:"app_name"`
Version string `json:"version"`
}
func getConfig() Config {
var config Config
err := json.Unmarshal(configData, &config)
if err != nil {
log.Fatal(err)
}
return config
}
func main() {
config := getConfig()
fmt.Println(config)
}

14
part_5/go_database/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,14 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"console": "integratedTerminal"
}
]
}

View File

@@ -0,0 +1,218 @@
package database
import (
"bufio"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
)
type DBType int
const (
SUAI DBType = iota
UNECON
)
type Database struct {
PathToSuaiDB string
PathToUneconDB string
SuaiUsers *Table[*User]
UneconUsers *Table[*User]
}
func NewDatabase(pathToSuaiDB, pathToUneconDB string) *Database {
db := &Database{
PathToSuaiDB: pathToSuaiDB,
PathToUneconDB: pathToUneconDB,
}
if _, err := os.Stat(pathToSuaiDB); os.IsNotExist(err) {
dir := filepath.Dir(pathToSuaiDB)
if err := os.MkdirAll(dir, 0755); err != nil {
fmt.Println("Error creating directory:", err)
}
file, err := os.Create(pathToSuaiDB)
if err != nil {
fmt.Println("Error creating file:", err)
}
file.Close()
db.SuaiUsers = NewTable[*User]("suai")
} else {
db.SuaiUsers = db.openTable(pathToSuaiDB, "suai")
}
if _, err := os.Stat(pathToUneconDB); os.IsNotExist(err) {
dir := filepath.Dir(pathToUneconDB)
if err := os.MkdirAll(dir, 0755); err != nil {
fmt.Println("Error creating directory:", err)
}
file, err := os.Create(pathToUneconDB)
if err != nil {
fmt.Println("Error creating file:", err)
}
file.Close()
db.UneconUsers = NewTable[*User]("unecon")
} else {
db.UneconUsers = db.openTable(pathToUneconDB, "unecon")
}
return db
}
func (db *Database) openTable(filePath, tableName string) *Table[*User] {
table := NewTable[*User](tableName)
file, err := os.Open(filePath)
if err != nil {
fmt.Println("Error opening file:", err)
return table
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
data := strings.Split(line, ",")
if len(data) >= 7 {
id, _ := strconv.Atoi(data[0])
yearOfBirth, _ := strconv.Atoi(data[2])
user := NewUser(
id,
data[1],
yearOfBirth,
data[3],
data[4],
data[5],
data[6],
)
table.Insert(user)
}
}
return table
}
func (db *Database) Save(dbType DBType) {
var filePath string
var users *Table[*User]
switch dbType {
case SUAI:
filePath = db.PathToSuaiDB
users = db.SuaiUsers
case UNECON:
filePath = db.PathToUneconDB
users = db.UneconUsers
}
file, err := os.Create(filePath)
if err != nil {
fmt.Println("Error opening file for writing:", err)
return
}
defer file.Close()
writer := bufio.NewWriter(file)
users.ForEach(func(user *User) {
line := fmt.Sprintf("%d,%s,%d,%s,%s,%s,%s\n",
user.ID(),
user.Nickname(),
user.YearOfBirth(),
user.Email(),
user.Phone(),
user.AccessLevel(),
user.PasswordHash(),
)
writer.WriteString(line)
})
writer.Flush()
}
func (db *Database) Insert(user *User, dbType DBType) bool {
var filePath string
var isOk bool
switch dbType {
case SUAI:
filePath = db.PathToSuaiDB
isOk = db.SuaiUsers.Insert(user)
case UNECON:
filePath = db.PathToUneconDB
isOk = db.UneconUsers.Insert(user)
}
if !isOk {
return false
}
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("Error opening file for appending:", err)
return false
}
defer file.Close()
line := fmt.Sprintf("%d,%s,%d,%s,%s,%s,%s\n",
user.ID(),
user.Nickname(),
user.YearOfBirth(),
user.Email(),
user.Phone(),
user.AccessLevel(),
user.PasswordHash(),
)
if _, err := file.WriteString(line); err != nil {
fmt.Println("Error writing to file:", err)
return false
}
return true
}
func (db *Database) Selection(dbType DBType,
attribute, value string) *Table[*User] {
switch dbType {
case SUAI:
return db.SuaiUsers.Selection(attribute, value)
case UNECON:
return db.UneconUsers.Selection(attribute, value)
default:
return NewTable[*User]("empty")
}
}
func (db *Database) Intersect(attribute, value string) *Table[*User] {
return db.SuaiUsers.Intersect(attribute, value, db.UneconUsers)
}
func (db *Database) Union() *Table[*User] {
return db.SuaiUsers.Union(db.UneconUsers)
}
func (db *Database) Remove(id string, dbType DBType) {
switch dbType {
case SUAI:
db.SuaiUsers.Remove(id)
fmt.Println(db.SuaiUsers)
case UNECON:
db.UneconUsers.Remove(id)
fmt.Println(db.UneconUsers)
}
}
func (db *Database) ShowDB(dbType DBType) {
switch dbType {
case SUAI:
fmt.Println(db.SuaiUsers)
case UNECON:
fmt.Println(db.UneconUsers)
}
}

View File

@@ -0,0 +1,8 @@
package database
type IAttribute interface {
Check(attribute, value string) bool
Change(attribute, value string) bool
String() string
}

View File

@@ -0,0 +1,155 @@
package database
import (
"fmt"
"strconv"
"strings"
)
type Node[T IAttribute] struct {
Data T
Next *Node[T]
}
type Table[T IAttribute] struct {
head *Node[T]
tail *Node[T]
Title string
}
func NewTable[T IAttribute](title string) *Table[T] {
return &Table[T]{Title: title}
}
func (t *Table[T]) First() T {
if t.head != nil {
return t.head.Data
}
var zero T
return zero
}
func (t *Table[T]) Last() T {
if t.tail != nil {
return t.tail.Data
}
var zero T
return zero
}
func (t *Table[T]) Contains(data T) bool {
user, ok := any(data).(*User)
if !ok {
return false
}
temp := t.head
for temp != nil {
if temp.Data.Check(FieldID, strconv.Itoa(user.ID())) {
return true
}
temp = temp.Next
}
return false
}
func (t *Table[T]) Insert(data T) bool {
if t.Contains(data) {
return false
}
node := &Node[T]{Data: data}
if t.head == nil {
t.head = node
t.tail = node
} else {
t.tail.Next = node
t.tail = node
}
return true
}
func (t *Table[T]) Remove(id string) {
var prev *Node[T]
curr := t.head
for curr != nil {
if curr.Data.Check("id", id) {
if prev == nil {
t.head = curr.Next
if t.head == nil {
t.tail = nil
}
} else {
prev.Next = curr.Next
if prev.Next == nil {
t.tail = prev
}
}
return
}
prev = curr
curr = curr.Next
}
}
func (t *Table[T]) Intersect(attribute, value string,
other *Table[T]) *Table[T] {
newTable := NewTable[T](fmt.Sprintf("%s-%s", t.Title, other.Title))
for temp := t.head; temp != nil; temp = temp.Next {
if temp.Data.Check(attribute, value) {
newTable.Insert(temp.Data)
}
}
for temp := other.head; temp != nil; temp = temp.Next {
if temp.Data.Check(attribute, value) &&
!newTable.Contains(temp.Data) {
newTable.Insert(temp.Data)
}
}
return newTable
}
func (t *Table[T]) Union(other *Table[T]) *Table[T] {
newTable := NewTable[T](fmt.Sprintf("%s-%s", t.Title, other.Title))
for temp := t.head; temp != nil; temp = temp.Next {
newTable.Insert(temp.Data)
}
for temp := other.head; temp != nil; temp = temp.Next {
if !newTable.Contains(temp.Data) {
newTable.Insert(temp.Data)
}
}
return newTable
}
func (t *Table[T]) Selection(attribute, value string) *Table[T] {
newTable := NewTable[T](t.Title + "-new")
for temp := t.head; temp != nil; temp = temp.Next {
if temp.Data.Check(attribute, value) {
newTable.Insert(temp.Data)
}
}
return newTable
}
func (t *Table[T]) ForEach(action func(T)) {
for temp := t.head; temp != nil; temp = temp.Next {
action(temp.Data)
}
}
func (t *Table[T]) String() string {
var sb strings.Builder
sb.WriteString(fmt.Sprintf("%s%s%s\n", strings.Repeat("*", 10),
t.Title, strings.Repeat("*", 10)))
for temp := t.head; temp != nil; temp = temp.Next {
sb.WriteString(fmt.Sprintf("%s\n", temp.Data.String()))
}
return sb.String()
}

View File

@@ -0,0 +1,132 @@
package database
import (
"fmt"
"strconv"
"strings"
)
type AccessLevel = string
const (
Student AccessLevel = "S"
Teacher AccessLevel = "T"
Admin AccessLevel = "A"
)
func AcsessLevelFromString(s string) AccessLevel {
switch strings.ToUpper(s) {
case "T":
return Teacher
case "A":
return Admin
default:
return Student
}
}
type UserTableField = string
const (
FieldID UserTableField = "id"
FieldNickname UserTableField = "nickname"
FieldYearOfBirth UserTableField = "yearOfBirth"
FieldEmail UserTableField = "email"
FieldPhone UserTableField = "phone"
FieldAccessLevel UserTableField = "accessLevel"
FieldPasswordHash UserTableField = "passwordHash"
)
type User struct {
id int
nickname string
yearOfBirth int
email string
phone string
accessLevel AccessLevel
passwordHash string
}
func NewUser(
id int,
nickname string,
yearOfBirth int,
email string,
phone string,
accessLevel string,
passwordHash string,
) *User {
return &User{
id: id,
nickname: nickname,
yearOfBirth: yearOfBirth,
email: email,
phone: phone,
accessLevel: AcsessLevelFromString(accessLevel),
passwordHash: passwordHash,
}
}
func (u *User) ID() int { return u.id }
func (u *User) Nickname() string { return u.nickname }
func (u *User) YearOfBirth() int { return u.yearOfBirth }
func (u *User) Email() string { return u.email }
func (u *User) Phone() string { return u.phone }
func (u *User) AccessLevel() string { return u.accessLevel }
func (u *User) PasswordHash() string { return u.passwordHash }
func (u *User) Change(attr, value string) bool {
switch attr {
case FieldNickname:
u.nickname = value
case FieldYearOfBirth:
v, err := strconv.Atoi(value)
if err != nil {
return false
}
u.yearOfBirth = v
case FieldEmail:
u.email = value
case FieldPhone:
u.phone = value
case FieldAccessLevel:
u.accessLevel = AcsessLevelFromString(value)
case FieldPasswordHash:
u.passwordHash = value
default:
return false
}
return true
}
func (u *User) Check(attr, value string) bool {
switch attr {
case FieldID:
v, err := strconv.Atoi(value)
return err == nil && u.id == v
case FieldNickname:
return u.nickname == value
case FieldYearOfBirth:
v, err := strconv.Atoi(value)
return err == nil && u.yearOfBirth == v
case FieldEmail:
return u.email == value
case FieldPhone:
return u.phone == value
case FieldAccessLevel:
return u.accessLevel == value
case FieldPasswordHash:
return u.passwordHash == value
default:
return false
}
}
func (u *User) String() string {
return fmt.Sprintf(
"User(id: %d, nickname: %s, yearOfBirth: %d, "+
"email: %s, phone: %s, acsessLevel: %s, passwordHash: %s)",
u.id, u.nickname, u.yearOfBirth, u.email,
u.phone, u.accessLevel, u.passwordHash,
)
}

View File

@@ -0,0 +1,3 @@
module go_database
go 1.24

View File

@@ -0,0 +1,16 @@
package main
import (
db "go_database/database"
"path/filepath"
)
func main() {
db := db.NewDatabase(
filepath.Join(".", "suai.txt"),
filepath.Join(".", "unecon.txt"),
)
menu := NewMenu(db)
menu.Loop()
}

214
part_5/go_database/menu.go Normal file
View File

@@ -0,0 +1,214 @@
package main
import (
"bufio"
"fmt"
db "go_database/database"
"os"
"strconv"
"strings"
)
type Menu struct {
database *db.Database
reader *bufio.Reader
}
func NewMenu(db *db.Database) *Menu {
return &Menu{
database: db,
reader: bufio.NewReader(os.Stdin),
}
}
func (m *Menu) Loop() {
for {
m.PrintMenu()
input, _ := m.reader.ReadString('\n')
input = strings.TrimSpace(input)
fmt.Println(strings.Repeat("x", 25))
switch input {
case "1":
m.AddUser()
case "2":
m.RemoveUser()
case "3":
m.ChangeUser()
case "4":
m.ShowUsers()
case "5":
m.Intersect()
case "6":
m.Union()
case "7":
m.SaveAndExit()
return
case "8":
return
}
}
}
func (m *Menu) PrintMenu() {
fmt.Println("1. Add User")
fmt.Println("2. Remove User")
fmt.Println("3. Change User")
fmt.Println("4. Show Users")
fmt.Println("5. Intersect Table")
fmt.Println("6. Union Table")
fmt.Println("7. Save and Exit")
fmt.Println("8. Exit")
}
func (m *Menu) readInput(prompt string) string {
fmt.Print(prompt)
input, _ := m.reader.ReadString('\n')
return strings.TrimSpace(input)
}
func (m *Menu) AddUser() {
try := func() bool {
idStr := m.readInput("Enter id: ")
id, err := strconv.Atoi(idStr)
if err != nil {
fmt.Println("Invalid ID format")
return false
}
nickname := m.readInput("Enter nickname: ")
yearStr := m.readInput("Enter year of birth: ")
yearOfBirth, err := strconv.Atoi(yearStr)
if err != nil {
fmt.Println("Invalid year format")
return false
}
email := m.readInput("Enter email: ")
phone := m.readInput("Enter phone: ")
passwordHash := m.readInput("Enter password hash: ")
accessLevel := m.readInput("Access level (A - Admin, " +
"T - Teacher, S - Student): ")
user := db.NewUser(
id,
nickname,
yearOfBirth,
email,
phone,
accessLevel,
passwordHash,
)
dbTypeStr := m.readInput("Add user to DB (S - SUAI, U - Unecon): ")
dbTypeStr = strings.ToUpper(dbTypeStr)
switch dbTypeStr {
case "S":
m.database.Insert(user, db.SUAI)
m.database.ShowDB(db.SUAI)
case "U":
m.database.Insert(user, db.UNECON)
m.database.ShowDB(db.UNECON)
default:
fmt.Println("(ノ-_-)ノ ミ ┴┴")
return false
}
return true
}
if !try() {
fmt.Println("WTF!!!!")
}
}
func (m *Menu) RemoveUser() {
dbTypeStr := m.readInput("Select DB (S - SUAI, U - Unecon): ")
dbTypeStr = strings.ToUpper(dbTypeStr)
var dbType db.DBType
switch dbTypeStr {
case "S":
dbType = db.SUAI
m.database.ShowDB(db.SUAI)
case "U":
dbType = db.UNECON
m.database.ShowDB(db.UNECON)
default:
fmt.Println("(ノ-_-)ノ ミ ┴┴")
return
}
id := m.readInput("Enter id: ")
m.database.Remove(id, dbType)
m.database.ShowDB(dbType)
}
func (m *Menu) ChangeUser() {
dbTypeStr := m.readInput("Select DB (S - SUAI, U - Unecon): ")
dbTypeStr = strings.ToUpper(dbTypeStr)
var dbType db.DBType
switch dbTypeStr {
case "S":
dbType = db.SUAI
m.database.ShowDB(db.SUAI)
case "U":
dbType = db.UNECON
m.database.ShowDB(db.UNECON)
default:
fmt.Println("(ノ-_-)ノ ミ ┴┴")
return
}
id := m.readInput("Enter id: ")
userTable := m.database.Selection(dbType, "id", id)
user := userTable.First()
if user == nil {
fmt.Println("User not found!")
return
}
field := m.readInput("Enter field: ")
newValue := m.readInput("Enter new value: ")
user.Change(field, newValue)
m.database.ShowDB(dbType)
}
func (m *Menu) ShowUsers() {
dbTypeStr := m.readInput("Select DB (S - SUAI, U - Unecon): ")
dbTypeStr = strings.ToUpper(dbTypeStr)
switch dbTypeStr {
case "S":
m.database.ShowDB(db.SUAI)
case "U":
m.database.ShowDB(db.UNECON)
default:
fmt.Println("(ノ-_-)ノ ミ ┴┴")
}
}
func (m *Menu) Intersect() {
field := m.readInput("Enter field: ")
value := m.readInput("Enter intersect value: ")
result := m.database.Intersect(field, value)
fmt.Println(result)
}
func (m *Menu) Union() {
result := m.database.Union()
fmt.Println(result)
}
func (m *Menu) SaveAndExit() {
m.database.Save(db.SUAI)
m.database.Save(db.UNECON)
}

View File

@@ -0,0 +1,5 @@
0,MADTeacher,1989,stasko@gmail.ru,+7xxxxxxx,T,adFF
1,Alex,1990,al@gmail.ru,+7x2x5xxx,A,adadFFxzxc
2,Max,2005,mmm@gmail.ru,+7xx654xx,S,20AFBB
3,Jack,2006,jj@gmail.ru,+7xx657xx,S,41FDF
5,FF,1999,mad@tr.ri,+7xx654xx,S,Hdndgu2397123

View File

@@ -0,0 +1,4 @@
0,Jack,2007,gf@gmail.ru,+7xx624xx,S,20AAAB
1,MADTeacher,1989,stasko@gmail.ru,+7xxxxxxx,T,adFF
2,Stas,1994,st@gmail.ru,+7x2x2xxx,A,adaFBB
6,Max,2009,mv@gmail.ru,+7xx657xx,S,41FDF

View File

@@ -0,0 +1,3 @@
module go_json_store
go 1.20

View File

@@ -0,0 +1,62 @@
package jsonstore
import (
"encoding/json"
"io"
"os"
"path/filepath"
)
type JSONFile struct {
Path string
}
func NewJSONFile(path string) *JSONFile {
dir := filepath.Dir(path)
if _, err := os.Stat(dir); os.IsNotExist(err) {
os.MkdirAll(dir, 0755)
}
return &JSONFile{Path: path}
}
func (j *JSONFile) Read() map[string]any {
file, err := os.Open(j.Path)
if err != nil {
if os.IsNotExist(err) {
return make(map[string]any)
}
return make(map[string]any)
}
defer file.Close()
data, err := io.ReadAll(file)
if err != nil {
return make(map[string]any)
}
if len(data) == 0 {
return make(map[string]any)
}
var result map[string]any
err = json.Unmarshal(data, &result)
if err != nil {
return make(map[string]any)
}
return result
}
func (j *JSONFile) Write(data map[string]any) error {
dir := filepath.Dir(j.Path)
if _, err := os.Stat(dir); os.IsNotExist(err) {
os.MkdirAll(dir, 0755)
}
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
return err
}
return os.WriteFile(j.Path, jsonData, 0644)
}

View File

@@ -0,0 +1,200 @@
package jsonstore
import (
"encoding/json"
"os"
"reflect"
)
type JSONStore struct {
filePath string
values map[string]interface{}
}
func NewJSONStore(path string) *JSONStore {
return &JSONStore{
filePath: path,
}
}
func (js *JSONStore) load() map[string]interface{} {
if js.values != nil {
return js.values
}
content, err := os.ReadFile(js.filePath)
if err != nil {
js.values = make(map[string]interface{})
return js.values
}
var data map[string]interface{}
if err := json.Unmarshal(content, &data); err != nil {
js.values = make(map[string]interface{})
return js.values
}
js.values = data
return js.values
}
func (js *JSONStore) Contains(key string) bool {
_, ok := js.load()[key]
return ok
}
func (js *JSONStore) Keys() []string {
keys := make([]string, 0)
for k := range js.load() {
keys = append(keys, k)
}
return keys
}
func (js *JSONStore) Values() []interface{} {
values := make([]interface{}, 0)
for _, v := range js.load() {
values = append(values, v)
}
return values
}
func (js *JSONStore) GetValue(key string) interface{} {
return js.load()[key]
}
func (js *JSONStore) GetBool(key string) *bool {
if v, ok := js.GetValue(key).(bool); ok {
return &v
}
return nil
}
func (js *JSONStore) GetInt(key string) *int {
// Т.к. все числа по умолчанию декодируются как float64,
// то сначала приводим к float64
if f, ok := js.GetValue(key).(float64); ok {
i := int(f)
return &i
}
return nil
}
func (js *JSONStore) GetFloat(key string) *float64 {
if v, ok := js.GetValue(key).(float64); ok {
return &v
}
return nil
}
func (js *JSONStore) GetString(key string) *string {
if v, ok := js.GetValue(key).(string); ok {
return &v
}
return nil
}
// Метод возвращает по ключу срез []interface{}.
// Если значение хранится как []interface{}, возвращаем его напрямую.
// Если значение хранится как []string, []int или []float64,
// преобразуем каждый элемент к interface{} для совместимости
// с Go JSON API. Это обеспечивает универсальный доступ к массивам
// любого типа, сохраненным в JSON.
func (js *JSONStore) GetList(key string) []interface{} {
// Получаем значение по ключу
val := js.GetValue(key)
// Если значение отсутствует, возвращаем nil
if val == nil {
return nil
}
// Если это уже []interface{} (тип, который возвращает
// json.Unmarshal), возвращаем напрямую
if v, ok := val.([]interface{}); ok {
return v
}
// Если это []string, преобразуем каждый элемент к interface{}
if v, ok := val.([]string); ok {
// Создаем новый срез с типом []interface{}
result := make([]interface{}, len(v))
// Преобразуем каждый элемент []string в interface{}
for i, s := range v {
result[i] = s
}
return result
}
// Если это []int, преобразуем каждый элемент к interface{}
if v, ok := val.([]int); ok {
// Создаем новый срез с типом []interface{}
result := make([]interface{}, len(v))
// Преобразуем каждый элемент []int в interface{}
for i, n := range v {
result[i] = n
}
return result
}
// Если это []float64 (тип, который возвращает json.Unmarshal),
// преобразуем каждый элемент к interface{}
if v, ok := val.([]float64); ok {
// Создаем новый срез с типом []interface{}
result := make([]interface{}, len(v))
// Преобразуем каждый элемент []float64 в interface{}
for i, n := range v {
result[i] = n
}
return result
}
// Если тип не поддерживается, возвращаем nil
return nil
}
func (js *JSONStore) GetMap(key string) map[string]interface{} {
val := js.GetValue(key)
if val == nil {
return nil
}
if m, ok := val.(map[string]interface{}); ok {
return m
}
// Попробуем привести через json, если тип не совпал
if b, err := json.Marshal(val); err == nil {
var m map[string]interface{}
if err := json.Unmarshal(b, &m); err == nil {
return m
}
}
return nil
}
func (js *JSONStore) ValueEquals(a, b interface{}) bool {
return reflect.DeepEqual(a, b)
}
func (js *JSONStore) SetValue(key string, value interface{}) {
values := js.load()
oldVal := values[key]
if value == nil {
delete(values, key)
js.save(values)
} else if oldVal == nil || !js.ValueEquals(oldVal, value) {
values[key] = value
js.save(values)
}
}
func (js *JSONStore) ResetValue(key string) {
values := js.load()
if _, exists := values[key]; exists {
delete(values, key)
js.save(values)
}
}
func (js *JSONStore) save(data map[string]interface{}) {
bytes, err := json.MarshalIndent(data, "", " ")
if err != nil {
return
}
_ = os.WriteFile(js.filePath, bytes, 0644)
js.values = data
}

View File

@@ -0,0 +1,167 @@
package main
import (
"fmt"
"go_json_store/jsonstore"
)
func main() {
store := jsonstore.NewJSONStore("store.json")
store.SetValue("map", map[string]int{"a": 1, "b": 2})
store.SetValue("strList", []string{"a", "b", "c"})
store.SetValue("intList", []int{1, 2, 3})
// Получение и приведение типов
rawStrList := store.GetList("strList")
var strList []string
for _, v := range rawStrList {
if s, ok := v.(string); ok {
strList = append(strList, s)
}
}
rawIntList := store.GetList("intList")
var intList []int
for _, v := range rawIntList {
if n, ok := v.(int); ok {
intList = append(intList, n)
}
}
rawMap := store.GetMap("map")
myMap := make(map[string]int)
for k, v := range rawMap {
switch n := v.(type) {
case int:
myMap[k] = n
case float64:
myMap[k] = int(n)
}
}
fmt.Printf("%T\n", strList) // []string
fmt.Printf("%T\n", intList) // []int
fmt.Printf("%T\n", myMap) // map[string]int
fmt.Println(strList) // [a b c]
fmt.Println(intList) // [1 2 3]
fmt.Println(myMap) // map[a:1 b:2]
boolVal := store.GetBool("bool")
fmt.Println(*boolVal) // true
intVal := store.GetInt("int")
fmt.Println(*intVal) // 55
floatVal := store.GetFloat("double")
fmt.Println(*floatVal) // 99.4
}
//*************** 3 ***************************
/*
func main() {
store := jsonstore.NewJSONStore("store.json")
store.ResetValue("map")
store.ResetValue("str")
fmt.Println(store.GetValue("map")) // <nil>
fmt.Println(store.GetValue("str")) // <nil>
}
*/
//*************** 2 ***************************
/*
func main() {
store := jsonstore.NewJSONStore("store.json")
store.SetValue("strList", "-_-")
store.SetValue("double", 99)
fmt.Println(store.GetValue("strList")) // -_-
fmt.Println(store.GetValue("double")) // 99
}
*/
//*************** 1 ***************************
/*
func main() {
store := jsonstore.NewJSONStore("store.json")
store.SetValue("strList", []string{"a", "b", "c"})
store.SetValue("int", 55)
store.SetValue("bool", true)
store.SetValue("double", 3.14)
store.SetValue("map", map[string]int{"a": 1, "b": 2})
store.SetValue("str", "(づ˶•༝•˶)づ♡")
fmt.Println(store.Values())
// [[a b c] 55 true 3.14 map[a:1 b:2] (づ˶•༝•˶)づ♡]
fmt.Println(store.Keys())
// [bool double map str strList int]
fmt.Println(store.Contains("strList")) // true
fmt.Println(store.GetValue("strList")) // [a b c]
fmt.Println(store.GetValue("int")) // 55
fmt.Println(store.GetValue("bool")) // true
fmt.Println(store.GetValue("double")) // 3.14
fmt.Println(store.GetValue("map")) // map[a:1 b:2]
fmt.Println(store.GetValue("str")) // (づ˶•༝•˶)づ♡
} */
/*func main() {
fmt.Println("Starting JSON Store Demo")
store := jsonstore.NewJSONStore("store.json")
// Set some values
mapValue := map[string]any{"a": 1, "b": 2}
strList := []any{"a", "b", "c"}
intList := []any{1, 2, 3}
store.SetValue("map", mapValue)
store.SetValue("strList", strList)
store.SetValue("intList", intList)
// Get values
retrievedStrList := store.GetList("strList")
retrievedIntList := store.GetList("intList")
retrievedMap := store.GetMap("map")
// Print results
fmt.Printf("strList type: %T\n", retrievedStrList)
fmt.Printf("intList type: %T\n", retrievedIntList)
fmt.Printf("map type: %T\n", retrievedMap)
fmt.Printf("strList: %v\n", retrievedStrList)
fmt.Printf("intList: %v\n", retrievedIntList)
fmt.Printf("map: %v\n", retrievedMap)
// Let's demonstrate more features similar to the commented section in the Dart code
store.SetValue("int", 55)
store.SetValue("bool", true)
store.SetValue("double", 3.14)
store.SetValue("str", "(づ˶•༝•˶)づ♡")
fmt.Println("\nAll values:", store.Values())
fmt.Println("All keys:", store.Keys())
fmt.Printf("Contains 'strList': %v\n", store.Contains("strList"))
fmt.Printf("Value of 'strList': %v\n", store.GetValue("strList"))
fmt.Printf("Value of 'int': %v\n", store.GetValue("int"))
fmt.Printf("Value of 'bool': %v\n", store.GetValue("bool"))
fmt.Printf("Value of 'double': %v\n", store.GetValue("double"))
fmt.Printf("Value of 'map': %v\n", store.GetValue("map"))
fmt.Printf("Value of 'str': %v\n", store.GetValue("str"))
// Update values
store.SetValue("strList", "-_-")
store.SetValue("double", 99)
fmt.Printf("\nUpdated 'strList': %v\n", store.GetValue("strList"))
fmt.Printf("Updated 'double': %v\n", store.GetValue("double"))
// Reset values
store.ResetValue("map")
store.ResetValue("str")
fmt.Printf("After reset, 'map': %v\n", store.GetValue("map"))
fmt.Printf("After reset, 'str': %v\n", store.GetValue("str"))
}
*/

View File

@@ -0,0 +1,19 @@
{
"bool": true,
"double": 99.4,
"int": 55,
"intList": [
1,
2,
3
],
"map": {
"a": 1,
"b": 2
},
"strList": [
"a",
"b",
"c"
]
}

14
part_5/tic_tac_toe/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,14 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}", // <- ставим запятую
"console": "integratedTerminal"
}
]
}

View File

@@ -0,0 +1,113 @@
package game
import (
"fmt"
)
const (
BoardDefaultSize int = 3
BoardMinSize int = 3
BoardMaxSize int = 9
)
type Board struct {
Board [][]BoardField `json:"board"`
Size int `json:"size"`
}
func NewBoard(size int) *Board {
board := make([][]BoardField, size)
for i := range board {
board[i] = make([]BoardField, size)
}
return &Board{Board: board, Size: size}
}
// Отображение игрового поля
func (b *Board) printBoard() {
fmt.Print(" ")
for i := range b.Size {
fmt.Printf("%d ", i+1)
}
fmt.Println()
for i := range b.Size {
fmt.Printf("%d ", i+1)
for j := range b.Size {
switch b.Board[i][j] {
case empty:
fmt.Print(". ")
case cross:
fmt.Print("X ")
case nought:
fmt.Print("O ")
}
}
fmt.Println()
}
}
// Проверка возможности и выполнения хода
func (b *Board) makeMove(x, y int) bool {
return b.Board[x][y] == empty
}
func (b *Board) setSymbol(x, y int, player BoardField) bool {
if b.makeMove(x, y) {
b.Board[x][y] = player
return true
}
return false
}
// Проверка выигрыша
func (b *Board) checkWin(player BoardField) bool {
// Проверка строк и столбцов
for i := range b.Size {
rowWin, colWin := true, true
for j := range b.Size {
if b.Board[i][j] != player {
rowWin = false
}
if b.Board[j][i] != player {
colWin = false
}
}
if rowWin || colWin {
return true
}
}
// Главная диагональ
mainDiag := true
for i := range b.Size {
if b.Board[i][i] != player {
mainDiag = false
break
}
}
if mainDiag {
return true
}
// Побочная диагональ
antiDiag := true
for i := range b.Size {
if b.Board[i][b.Size-i-1] != player {
antiDiag = false
break
}
}
return antiDiag
}
// Проверка на ничью
func (b *Board) checkDraw() bool {
for i := range b.Size {
for j := range b.Size {
if b.Board[i][j] == empty {
return false
}
}
}
return true
}

View File

@@ -0,0 +1,10 @@
package game
type BoardField int
// фигуры в клетке поля
const (
empty BoardField = iota
cross
nought
)

View File

@@ -0,0 +1,122 @@
package game
import (
"bufio"
"fmt"
"strconv"
"strings"
)
type Game struct {
Board *Board `json:"board"`
Player *Player `json:"player"`
Reader *bufio.Reader `json:"-"`
State GameState `json:"state"`
Saver IGameSaver `json:"-"`
}
func NewGame(board Board, player Player,
reader *bufio.Reader, saver IGameSaver) *Game {
return &Game{
Board: &board,
Player: &player,
Reader: reader,
State: playing,
Saver: saver,
}
}
func (g *Game) updateState() {
if g.Board.checkWin(g.Player.Figure) {
if g.Player.Figure == cross {
g.State = crossWin
} else {
g.State = noughtWin
}
} else if g.Board.checkDraw() {
g.State = draw
}
}
func (g *Game) saveCheck(input string) bool {
if input == "save" {
fmt.Println("Enter file name: ")
fileName, err := g.Reader.ReadString('\n')
if err != nil {
fmt.Println("Invalid input. Please try again.")
return false
}
fileName = strings.TrimSpace(fileName)
err = g.Saver.SaveGame(fileName, g)
if err != nil {
fmt.Println("Error saving game.")
return false
}
fmt.Println("Game saved successfully!!!")
return true
}
return false
}
// Игровой цикл
func (g *Game) Play() {
for g.State == playing {
g.Board.printBoard()
fmt.Printf(
"%s's turn. Enter row and column (e.g. 1 2): ",
g.Player.getSymbol())
input, err := g.Reader.ReadString('\n')
input = strings.TrimSpace(input)
if err != nil {
fmt.Println("Invalid input. Please try again.")
continue
}
input = strings.TrimSpace(input)
if input == "q" {
g.State = quit
break
}
if g.saveCheck(input) {
continue
}
parts := strings.Fields(input)
if len(parts) != 2 {
fmt.Println("Invalid input. Please try again.")
continue
}
row, err1 := strconv.Atoi(parts[0])
col, err2 := strconv.Atoi(parts[1])
if err1 != nil || err2 != nil ||
row < 1 || col < 1 || row > g.Board.Size ||
col > g.Board.Size {
fmt.Println("Invalid input. Please try again.")
continue
}
if g.Board.setSymbol(row-1, col-1, g.Player.Figure) {
g.updateState()
g.Player.switchPlayer()
} else {
fmt.Println("This cell is already occupied!")
}
}
g.Board.printBoard()
if g.State == crossWin {
fmt.Println("X wins!")
} else if g.State == noughtWin {
fmt.Println("O wins!")
} else if g.State == draw {
fmt.Println("It's a draw!")
} else {
fmt.Println("Game over!")
}
}

View File

@@ -0,0 +1,12 @@
package game
type GameState int
// состояние игрового процесса
const (
playing GameState = iota
draw
crossWin
noughtWin
quit
)

View File

@@ -0,0 +1,9 @@
package game
type IGameLoader interface {
LoadGame(path string) (*Game, error)
}
type IGameSaver interface {
SaveGame(path string, game *Game) error
}

View File

@@ -0,0 +1,50 @@
package game
import (
"encoding/json"
"os"
"strings"
)
func NewJsonGameLoader() IGameLoader {
return &JsonGameLoader{}
}
type JsonGameLoader struct{}
func (j *JsonGameLoader) LoadGame(path string) (*Game, error) {
if !strings.HasSuffix(path, ".json") {
path += ".json"
}
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
decoder := json.NewDecoder(file)
var game Game
err = decoder.Decode(&game)
if err != nil {
return nil, err
}
return &game, nil
}
func (j *JsonGameLoader) SaveGame(path string, game *Game) error {
if !strings.HasSuffix(path, ".json") {
path += ".json"
}
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()
encoder := json.NewEncoder(file)
err = encoder.Encode(game)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,24 @@
package game
type Player struct {
Figure BoardField `json:"figure"`
}
func NewPlayer() *Player {
return &Player{Figure: cross}
}
func (p *Player) switchPlayer() {
if p.Figure == cross {
p.Figure = nought
} else {
p.Figure = cross
}
}
func (p *Player) getSymbol() string {
if p.Figure == cross {
return "X"
}
return "O"
}

View File

@@ -0,0 +1,3 @@
module tic-tac-toe
go 1.24.0

View File

@@ -0,0 +1,76 @@
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
"tic-tac-toe/game"
)
func main() {
reader := bufio.NewReader(os.Stdin)
loader := game.NewJsonGameLoader()
boardSize := 0
for {
fmt.Println("1 - load game")
fmt.Println("2 - new game")
fmt.Println("q - quit")
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
switch input {
case "1":
var loadedGame *game.Game
var err error
for {
fmt.Println("Enter file name: ")
fileName, _ := reader.ReadString('\n')
fileName = strings.TrimSpace(fileName)
loadedGame, err = loader.LoadGame(fileName)
if err != nil {
fmt.Println("Error loading game.")
continue
}
break
}
loadedGame.Reader = reader
loadedGame.Saver = loader.(game.IGameSaver)
loadedGame.Play()
case "2":
for {
fmt.Print("Enter the size of the board (3-9): ")
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error reading input.")
continue
}
input = strings.TrimSpace(input)
boardSize, err = strconv.Atoi(input)
if err != nil {
// Использовать предыдущий размер по умолчанию
boardSize = game.BoardDefaultSize
}
if boardSize < game.BoardMinSize ||
boardSize > game.BoardMaxSize {
fmt.Println("Invalid board size.")
} else {
break
}
}
board := game.NewBoard(boardSize)
player := game.NewPlayer()
game := game.NewGame(*board, *player, reader,
loader.(game.IGameSaver))
game.Play()
case "q":
return
default:
fmt.Println("Invalid input. Please try again.")
return
}
}
}

View File

@@ -0,0 +1 @@
{"board":{"board":[[0,2,0,0],[0,0,1,0],[0,0,0,0],[0,0,1,0]],"size":4},"player":{"figure":2},"state":0}