mirror of
https://github.com/MADTeacher/go_basics.git
synced 2025-11-23 21:34:47 +02:00
init
This commit is contained in:
46
part_10/10.1/udp/client/client.go
Normal file
46
part_10/10.1/udp/client/client.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func RunClient(port int) {
|
||||
s, _ := net.ResolveUDPAddr("udp4", fmt.Sprintf("localhost:%d", port))
|
||||
connection, err := net.DialUDP("udp4", nil, s)
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf("The UDP server is %s\n", connection.RemoteAddr().String())
|
||||
defer connection.Close()
|
||||
count := 0
|
||||
for {
|
||||
data := []byte(fmt.Sprintf("%d)Hello!\n", count))
|
||||
fmt.Print("->", string(data))
|
||||
_, err = connection.Write(data)
|
||||
|
||||
checkErr(err)
|
||||
|
||||
buffer := make([]byte, 1024)
|
||||
n, _, err := connection.ReadFromUDP(buffer)
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf("<-: %s", string(buffer[0:n]))
|
||||
count++
|
||||
if count >= 5 {
|
||||
data := []byte("STOP")
|
||||
fmt.Println("->", string(data))
|
||||
_, err = connection.Write(data)
|
||||
checkErr(err)
|
||||
|
||||
fmt.Println("Finished!")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
3
part_10/10.1/udp/go.mod
Normal file
3
part_10/10.1/udp/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module udp
|
||||
|
||||
go 1.24
|
||||
38
part_10/10.1/udp/main.go
Normal file
38
part_10/10.1/udp/main.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"udp/client"
|
||||
"udp/server"
|
||||
)
|
||||
|
||||
const PORT = 8081
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Println("You didn't select a launch option!!!")
|
||||
return
|
||||
}
|
||||
numGR, err := strconv.Atoi(os.Args[1])
|
||||
checkErr(err)
|
||||
|
||||
switch numGR {
|
||||
case 1:
|
||||
fmt.Println("Server is running")
|
||||
server.RunServer(PORT)
|
||||
case 2:
|
||||
fmt.Println("Client is running")
|
||||
client.RunClient(PORT)
|
||||
default:
|
||||
log.Fatal("What pokemon is this?")
|
||||
}
|
||||
}
|
||||
44
part_10/10.1/udp/server/server.go
Normal file
44
part_10/10.1/udp/server/server.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func RunServer(port int) {
|
||||
s, err := net.ResolveUDPAddr("udp4", fmt.Sprintf(":%d", port))
|
||||
checkErr(err)
|
||||
|
||||
connection, err := net.ListenUDP("udp4", s)
|
||||
checkErr(err)
|
||||
|
||||
defer connection.Close()
|
||||
buffer := make([]byte, 1024)
|
||||
fmt.Println("Oo")
|
||||
for {
|
||||
n, addr, err := connection.ReadFromUDP(buffer) // ждем подсоединение клиента
|
||||
checkErr(err)
|
||||
fmt.Printf("<- %s", string(buffer[0:n]))
|
||||
|
||||
if strings.TrimSpace(string(buffer[0:n])) == "STOP" {
|
||||
fmt.Println()
|
||||
fmt.Println("Exiting UDP server!")
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
fmt.Printf("->: %s", string(buffer))
|
||||
_, err = connection.WriteToUDP(buffer, addr)
|
||||
checkErr(err)
|
||||
}
|
||||
}
|
||||
53
part_10/10.2/tcp/client/client.go
Normal file
53
part_10/10.2/tcp/client/client.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func RunClient(port int) {
|
||||
// запускает реализацию клиента TCP и соединяет вас с нужным TCP-сервером
|
||||
connection, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port))
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf("The TCP server is %s\n", connection.RemoteAddr().String())
|
||||
defer connection.Close()
|
||||
count := 0
|
||||
for {
|
||||
// отправка сообщения на сервер
|
||||
data := []byte(fmt.Sprintf("%d)Hello!\n", count))
|
||||
fmt.Print("->", string(data))
|
||||
fmt.Fprint(connection, fmt.Sprintf("%d)Hello!\n", count))
|
||||
// или
|
||||
//_, err = connection.Write(data)
|
||||
// checkErr(err)
|
||||
|
||||
// считываем ответ TCP-сервера
|
||||
message, err := bufio.NewReader(connection).ReadString('\n')
|
||||
// или
|
||||
// buffer := make([]byte, 1024)
|
||||
// _, err := connection.Read(buffer)
|
||||
// message := string(buffer)
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf("<-: %s", message)
|
||||
count++
|
||||
if count >= 5 {
|
||||
data := []byte("STOP")
|
||||
fmt.Println("->", string(data))
|
||||
_, err = connection.Write(data)
|
||||
checkErr(err)
|
||||
|
||||
fmt.Println("Finished!")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
3
part_10/10.2/tcp/go.mod
Normal file
3
part_10/10.2/tcp/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module udp/server
|
||||
|
||||
go 1.24
|
||||
38
part_10/10.2/tcp/main.go
Normal file
38
part_10/10.2/tcp/main.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"udp/server/client"
|
||||
"udp/server/server"
|
||||
)
|
||||
|
||||
const PORT = 8081
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Println("You didn't select a launch option!!!")
|
||||
return
|
||||
}
|
||||
numGR, err := strconv.Atoi(os.Args[1])
|
||||
checkErr(err)
|
||||
|
||||
switch numGR {
|
||||
case 1:
|
||||
fmt.Println("Server is running")
|
||||
server.RunServer(PORT)
|
||||
case 2:
|
||||
fmt.Println("Client is running")
|
||||
client.RunClient(PORT)
|
||||
default:
|
||||
log.Fatal("What pokemon is this?")
|
||||
}
|
||||
}
|
||||
62
part_10/10.2/tcp/server/server.go
Normal file
62
part_10/10.2/tcp/server/server.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
}
|
||||
|
||||
func handleConnection(connection net.Conn) {
|
||||
defer connection.Close()
|
||||
|
||||
buffer := make([]byte, 1024)
|
||||
for {
|
||||
n, err := connection.Read(buffer) // считывание данных
|
||||
checkErr(err)
|
||||
fmt.Printf("Receive: %s from %s\n",
|
||||
string(buffer[0:n-1]), connection.RemoteAddr().String())
|
||||
|
||||
if strings.TrimSpace(string(buffer[0:n])) == "STOP" {
|
||||
// завершение работы сервера
|
||||
fmt.Println()
|
||||
fmt.Printf("Close connection with client: %s\n",
|
||||
connection.RemoteAddr().String())
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
fmt.Printf("Send : %s to %s\n",
|
||||
string(buffer[0:n-1]), connection.RemoteAddr().String())
|
||||
_, err = connection.Write(buffer) // отправка сообщения клиенту
|
||||
checkErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
func RunServer(port int) {
|
||||
// net.Listen возвращает Listener переменную,
|
||||
// которая является общим сетевым прослушивателем для потоковых протоколов
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||
checkErr(err)
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
for {
|
||||
connection, err := listener.Accept() // ожидание подключения клиента к серверу
|
||||
// Только после успешного вызова Accept()TCP-сервер может начать
|
||||
// взаимодействовать с TCP-клиентами
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
go handleConnection(connection)
|
||||
}
|
||||
}
|
||||
77
part_10/10.3/tcp-chat/client/client.go
Normal file
77
part_10/10.3/tcp-chat/client/client.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var waitingGr sync.WaitGroup
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func sendMessage(connection net.Conn, waitingGr *sync.WaitGroup) {
|
||||
defer waitingGr.Done()
|
||||
for {
|
||||
reader := bufio.NewReader(os.Stdin) // считываем введенное сообщение
|
||||
text, _ := reader.ReadString('\n')
|
||||
|
||||
if strings.TrimSuffix(strings.TrimSpace(text), "\r\n") == "/stop" {
|
||||
// завершение работы клиента
|
||||
break
|
||||
} else {
|
||||
_, err := connection.Write([]byte(text))
|
||||
checkErr(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func receiveMessage(connection net.Conn, waitingGr *sync.WaitGroup) {
|
||||
defer waitingGr.Done()
|
||||
for {
|
||||
// ждем сообщение от сервера и считываем его
|
||||
message, err := bufio.NewReader(connection).ReadString('\n')
|
||||
|
||||
if err == io.EOF {
|
||||
fmt.Println("Connection close!")
|
||||
break
|
||||
} else if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
break
|
||||
}
|
||||
|
||||
message = message[:len(message)-1] // обрезаем символ перевода на следующую строку
|
||||
fmt.Println(string(message))
|
||||
}
|
||||
}
|
||||
|
||||
func RunClient(port int) {
|
||||
// запускает реализацию клиента TCP и соединяет вас с нужным TCP-сервером
|
||||
connection, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port))
|
||||
checkErr(err)
|
||||
|
||||
fmt.Printf("The TCP server is %s\n", connection.RemoteAddr().String())
|
||||
defer connection.Close()
|
||||
|
||||
waitingGr.Add(1)
|
||||
|
||||
fmt.Println("Enter name: ")
|
||||
temp := bufio.NewReader(os.Stdin)
|
||||
userName, _ := temp.ReadString('\n')
|
||||
_, err = connection.Write([]byte(userName))
|
||||
checkErr(err)
|
||||
|
||||
go sendMessage(connection, &waitingGr)
|
||||
go receiveMessage(connection, &waitingGr)
|
||||
|
||||
waitingGr.Wait()
|
||||
}
|
||||
3
part_10/10.3/tcp-chat/go.mod
Normal file
3
part_10/10.3/tcp-chat/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module tcp/server
|
||||
|
||||
go 1.24
|
||||
38
part_10/10.3/tcp-chat/main.go
Normal file
38
part_10/10.3/tcp-chat/main.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"tcp/server/client"
|
||||
"tcp/server/server"
|
||||
)
|
||||
|
||||
const PORT = 8081
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Println("You didn't select a launch option!!!")
|
||||
return
|
||||
}
|
||||
numGR, err := strconv.Atoi(os.Args[1])
|
||||
checkErr(err)
|
||||
|
||||
switch numGR {
|
||||
case 1:
|
||||
fmt.Println("Server is running")
|
||||
server.RunServer(PORT)
|
||||
case 2:
|
||||
fmt.Println("Client is running")
|
||||
client.RunClient(PORT)
|
||||
default:
|
||||
log.Fatal("What pokemon is this?")
|
||||
}
|
||||
}
|
||||
85
part_10/10.3/tcp-chat/server/server.go
Normal file
85
part_10/10.3/tcp-chat/server/server.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
var connections []net.Conn
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
}
|
||||
|
||||
func handleConnection(connection net.Conn) {
|
||||
connections = append(connections, connection)
|
||||
userName, _ := bufio.NewReader(connection).ReadString('\n')
|
||||
userName = userName[:len(userName)-2]
|
||||
_, err := connection.Write([]byte("Hi " + userName + "\n"))
|
||||
checkErr(err)
|
||||
|
||||
for {
|
||||
text, err := bufio.NewReader(connection).ReadString('\n')
|
||||
if err != nil {
|
||||
connection.Close()
|
||||
removeConnection(connection)
|
||||
broadCastMessage(userName+" is offline\n", connection)
|
||||
break
|
||||
}
|
||||
|
||||
broadCastMessage(userName+":"+text, connection)
|
||||
}
|
||||
}
|
||||
|
||||
func removeConnection(connection net.Conn) {
|
||||
var i int
|
||||
|
||||
for i = range connections {
|
||||
if connections[i] == connection {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(connections) > 1 {
|
||||
connections = append(connections[:i], connections[i+1:]...)
|
||||
} else {
|
||||
connections = nil
|
||||
}
|
||||
}
|
||||
|
||||
func broadCastMessage(msg string, connection net.Conn) {
|
||||
// отправка сообщения всем клиентам
|
||||
for _, c := range connections {
|
||||
if connection != c {
|
||||
_, err := c.Write([]byte(msg))
|
||||
checkErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
msg = msg[:len(msg)-1]
|
||||
fmt.Println(msg)
|
||||
}
|
||||
|
||||
func RunServer(port int) {
|
||||
// net.Listen возвращает Listener переменную,
|
||||
// которая является общим сетевым прослушивателем для потоковых протоколов
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||
checkErr(err)
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
for {
|
||||
connection, err := listener.Accept() // ожидание подключения клиента к серверу
|
||||
// Только после успешного вызова Accept()TCP-сервер может начать
|
||||
// взаимодействовать с TCP-клиентами
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
go handleConnection(connection)
|
||||
}
|
||||
}
|
||||
5
part_10/10.4/golang/todo-service/.vscode/settings.json
vendored
Normal file
5
part_10/10.4/golang/todo-service/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"yaml.schemas": {
|
||||
"swaggerviewer:openapi": "file:///e%3A/code/golang/todo-service/todo-service-api.yml"
|
||||
}
|
||||
}
|
||||
98
part_10/10.4/golang/todo-service/db/db.go
Normal file
98
part_10/10.4/golang/todo-service/db/db.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
_ "database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type SQLiteRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewSQLiteRepository() *SQLiteRepository {
|
||||
var db *gorm.DB
|
||||
|
||||
if _, err := os.Stat(dbName); os.IsNotExist(err) {
|
||||
db, err = gorm.Open(sqlite.Open(dbName), &gorm.Config{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println("DB isn't exist")
|
||||
db.AutoMigrate(&Project{}, &Task{})
|
||||
putDefaultValuesToDB(db)
|
||||
} else {
|
||||
db, err = gorm.Open(sqlite.Open(dbName), &gorm.Config{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println("DB already exists")
|
||||
}
|
||||
|
||||
return &SQLiteRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func putDefaultValuesToDB(db *gorm.DB) {
|
||||
firstProject := Project{
|
||||
Name: "Go",
|
||||
Description: "Roadmap for learning Go",
|
||||
}
|
||||
secondProject := Project{
|
||||
Name: "One Year",
|
||||
Description: "Tasks for the year",
|
||||
}
|
||||
db.Create(&firstProject)
|
||||
db.Create(&secondProject)
|
||||
db.Create(&Task{
|
||||
Name: "Variable",
|
||||
Description: "Learning Go build-in variables",
|
||||
Priority: 1,
|
||||
Project: &firstProject,
|
||||
})
|
||||
db.Create(&Task{
|
||||
Name: "Struct",
|
||||
Description: "Learning use struct in OOP code",
|
||||
Priority: 3,
|
||||
Project: &firstProject,
|
||||
})
|
||||
db.Create(&Task{
|
||||
Name: "Goroutine",
|
||||
Description: "Learning concurrent programming",
|
||||
Priority: 5,
|
||||
Project: &firstProject,
|
||||
})
|
||||
db.Create(&Task{
|
||||
Name: "DataBase",
|
||||
Description: "How write app with db",
|
||||
Priority: 1,
|
||||
Project: &firstProject,
|
||||
})
|
||||
db.Create(&Task{
|
||||
Name: "PhD",
|
||||
Description: "Ph.D. in Technical Sciences",
|
||||
Priority: 5,
|
||||
Project: &secondProject,
|
||||
})
|
||||
db.Create(&Task{
|
||||
Name: "Losing weight",
|
||||
Description: "Exercise and eat less chocolate",
|
||||
Priority: 2,
|
||||
Project: &secondProject,
|
||||
})
|
||||
db.Create(&Task{
|
||||
Name: "Пафос и превозмогание",
|
||||
Description: "10к подписчиков на канале",
|
||||
Priority: 2,
|
||||
Project: &secondProject,
|
||||
})
|
||||
}
|
||||
|
||||
func (r *SQLiteRepository) Close() {
|
||||
|
||||
}
|
||||
12
part_10/10.4/golang/todo-service/db/db_definition.go
Normal file
12
part_10/10.4/golang/todo-service/db/db_definition.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package db
|
||||
|
||||
import "errors"
|
||||
|
||||
const dbName = "todo.db"
|
||||
|
||||
var (
|
||||
ErrDuplicate = errors.New("record already exists")
|
||||
ErrNotExists = errors.New("row not exists")
|
||||
ErrUpdateFailed = errors.New("update failed")
|
||||
ErrDeleteFailed = errors.New("delete failed")
|
||||
)
|
||||
17
part_10/10.4/golang/todo-service/db/models.go
Normal file
17
part_10/10.4/golang/todo-service/db/models.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package db
|
||||
|
||||
type Project struct {
|
||||
ID int `json:"id" gorm:"primary_key;autoIncrement:true;not null"`
|
||||
Name string `json:"name" gorm:"unique;not null"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type Task struct {
|
||||
ID int `json:"id" gorm:"primary_key;autoIncrement;not null"`
|
||||
Name string `json:"name" gorm:"not null"`
|
||||
Description string `json:"description" gorm:"not null"`
|
||||
Priority uint8 `json:"priority" gorm:"not null"`
|
||||
IsDone bool `json:"isDone" gorm:"not null"`
|
||||
ProjectID int `json:"projectID" gorm:"not null"`
|
||||
Project *Project `gorm:"foreignKey:ProjectID;references:ID"`
|
||||
}
|
||||
49
part_10/10.4/golang/todo-service/db/projects_crud.go
Normal file
49
part_10/10.4/golang/todo-service/db/projects_crud.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
func (r *SQLiteRepository) AddProject(project Project) (*Project, error) {
|
||||
tx := r.db.Create(&project)
|
||||
if tx.Error != nil {
|
||||
var sqliteErr sqlite3.Error
|
||||
if errors.As(tx.Error, &sqliteErr) {
|
||||
if errors.Is(sqliteErr.ExtendedCode, sqlite3.ErrConstraintUnique) {
|
||||
return nil, ErrDuplicate
|
||||
}
|
||||
}
|
||||
return nil, tx.Error
|
||||
}
|
||||
|
||||
return &project, nil
|
||||
}
|
||||
|
||||
func (r *SQLiteRepository) DeleteProject(projectID int) error {
|
||||
tx := r.db.Delete(&Project{ID: projectID})
|
||||
if tx.Error != nil {
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
rowsAffected := tx.RowsAffected
|
||||
if rowsAffected == 0 {
|
||||
return ErrDeleteFailed
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SQLiteRepository) GetAllProjects() ([]Project, error) {
|
||||
var projects []Project
|
||||
tx := r.db.Find(&projects)
|
||||
if tx.Error != nil {
|
||||
return nil, tx.Error
|
||||
}
|
||||
if tx.RowsAffected == 0 {
|
||||
return nil, ErrNotExists
|
||||
}
|
||||
|
||||
return projects, nil
|
||||
}
|
||||
73
part_10/10.4/golang/todo-service/db/tasks_crud.go
Normal file
73
part_10/10.4/golang/todo-service/db/tasks_crud.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package db
|
||||
|
||||
import "errors"
|
||||
|
||||
func (r *SQLiteRepository) AddTask(task Task) (*Task, error) {
|
||||
tx := r.db.Create(&task)
|
||||
if tx.Error != nil {
|
||||
return nil, tx.Error
|
||||
}
|
||||
|
||||
return &task, nil
|
||||
}
|
||||
|
||||
func (r *SQLiteRepository) DeleteTask(taskID int) error {
|
||||
tx := r.db.Delete(&Task{ID: taskID})
|
||||
if tx.Error != nil {
|
||||
return tx.Error
|
||||
}
|
||||
|
||||
rowsAffected := tx.RowsAffected
|
||||
if rowsAffected == 0 {
|
||||
return ErrDeleteFailed
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SQLiteRepository) GetAllTasks() (tasks []Task, err error) {
|
||||
tx := r.db.Find(&tasks)
|
||||
if tx.Error != nil {
|
||||
return nil, tx.Error
|
||||
}
|
||||
if tx.RowsAffected == 0 {
|
||||
return nil, ErrNotExists
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *SQLiteRepository) GetProjectTasks(projectID int) (tasks []Task, err error) {
|
||||
if projectID == 0 {
|
||||
return nil, errors.New("invalid updated ID")
|
||||
}
|
||||
|
||||
tx := r.db.Where("project_id", projectID).Find(&tasks)
|
||||
if tx.Error != nil {
|
||||
return nil, tx.Error
|
||||
}
|
||||
if tx.RowsAffected == 0 {
|
||||
return nil, ErrNotExists
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *SQLiteRepository) TaskDone(taskId int) error {
|
||||
if taskId == 0 {
|
||||
return errors.New("invalid updated ID")
|
||||
}
|
||||
pjTask := &Task{ID: taskId}
|
||||
tx := r.db.Find(&pjTask)
|
||||
if tx.Error != nil {
|
||||
return tx.Error
|
||||
}
|
||||
pjTask.IsDone = true
|
||||
r.db.Save(&pjTask)
|
||||
rowsAffected := tx.RowsAffected
|
||||
if rowsAffected == 0 {
|
||||
return ErrUpdateFailed
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
16
part_10/10.4/golang/todo-service/go.mod
Normal file
16
part_10/10.4/golang/todo-service/go.mod
Normal file
@@ -0,0 +1,16 @@
|
||||
module golang/todo-service
|
||||
|
||||
go 1.24
|
||||
|
||||
require (
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
gorm.io/driver/sqlite v1.5.7
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
gorm.io/gorm v1.25.12 // indirect
|
||||
)
|
||||
16
part_10/10.4/golang/todo-service/go.sum
Normal file
16
part_10/10.4/golang/todo-service/go.sum
Normal file
@@ -0,0 +1,16 @@
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
|
||||
gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
|
||||
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde h1:9DShaph9qhkIYw7QF91I/ynrr4cOO2PZra2PFD7Mfeg=
|
||||
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
20
part_10/10.4/golang/todo-service/main.go
Normal file
20
part_10/10.4/golang/todo-service/main.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"golang/todo-service/db"
|
||||
"golang/todo-service/service"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const PORT = "8080"
|
||||
|
||||
func main() {
|
||||
|
||||
rep := db.NewSQLiteRepository()
|
||||
defer rep.Close()
|
||||
|
||||
router := service.NewRouter(rep)
|
||||
log.Printf("Server started")
|
||||
log.Fatal(http.ListenAndServe(":"+PORT, router))
|
||||
}
|
||||
22
part_10/10.4/golang/todo-service/service/api_models.go
Normal file
22
part_10/10.4/golang/todo-service/service/api_models.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package service
|
||||
|
||||
import "golang/todo-service/db"
|
||||
|
||||
type ErrorResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type GoodResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
ID int `json:"id"`
|
||||
}
|
||||
|
||||
type ProjectsList struct {
|
||||
Items []db.Project `json:"items,omitempty"`
|
||||
}
|
||||
|
||||
type TasksList struct {
|
||||
Items []db.Task `json:"items,omitempty"`
|
||||
}
|
||||
87
part_10/10.4/golang/todo-service/service/api_project.go
Normal file
87
part_10/10.4/golang/todo-service/service/api_project.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"golang/todo-service/db"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func deleteProject(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
params := mux.Vars(r)
|
||||
|
||||
idStr, ok := params["id"]
|
||||
if !ok {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
err = repository.DeleteProject(id)
|
||||
if err != nil {
|
||||
errorResponse(w, ErrorResponse{http.StatusNotFound,
|
||||
"Project not found"})
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func addProject(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
var project db.Project
|
||||
reqBody, err := io.ReadAll(r.Body)
|
||||
if err == nil {
|
||||
json.Unmarshal(reqBody, &project)
|
||||
if project.Name == "" {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
project.ID = 0
|
||||
project, err := repository.AddProject(project)
|
||||
if err != nil {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Project with that name already exists"})
|
||||
return
|
||||
}
|
||||
|
||||
goodResponse := GoodResponse{
|
||||
Code: 201,
|
||||
Message: "Проект создан",
|
||||
ID: project.ID,
|
||||
}
|
||||
jsonGoodResponse, _ := json.Marshal(goodResponse)
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write(jsonGoodResponse)
|
||||
return
|
||||
}
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
}
|
||||
|
||||
func getProjects(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
|
||||
progects, err := repository.GetAllProjects()
|
||||
if err != nil || len(progects) == 0 {
|
||||
errorResponse(w, ErrorResponse{http.StatusNotFound,
|
||||
"Projects not found"})
|
||||
return
|
||||
}
|
||||
|
||||
projectsList := ProjectsList{progects}
|
||||
jsonGoodResponse, _ := json.Marshal(projectsList)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(jsonGoodResponse)
|
||||
}
|
||||
153
part_10/10.4/golang/todo-service/service/api_task.go
Normal file
153
part_10/10.4/golang/todo-service/service/api_task.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"golang/todo-service/db"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func deleteTask(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
queryStr := r.URL.Query()
|
||||
|
||||
idStr, ok := queryStr["id"]
|
||||
if !ok {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
if len(idStr) == 0 {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(idStr[0])
|
||||
if err != nil {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
err = repository.DeleteTask(id)
|
||||
if err != nil {
|
||||
errorResponse(w, ErrorResponse{http.StatusNotFound,
|
||||
"Task not found"})
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func getTask(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
queryStr := r.URL.Query()
|
||||
|
||||
idStr, ok := queryStr["projectID"]
|
||||
if !ok {
|
||||
tasks, err := repository.GetAllTasks()
|
||||
if err != nil || len(tasks) == 0 {
|
||||
errorResponse(w, ErrorResponse{http.StatusNotFound,
|
||||
"Tasks not found"})
|
||||
return
|
||||
}
|
||||
// возвращаем все имеющиеся задачи
|
||||
projectsList := TasksList{tasks}
|
||||
jsonGoodResponse, _ := json.Marshal(projectsList)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(jsonGoodResponse)
|
||||
return
|
||||
}
|
||||
|
||||
if len(idStr) == 0 {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(idStr[0])
|
||||
if err != nil {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
tasks, err := repository.GetProjectTasks(id)
|
||||
if err != nil || len(tasks) == 0 {
|
||||
errorResponse(w, ErrorResponse{http.StatusNotFound,
|
||||
"Tasks not found"})
|
||||
return
|
||||
}
|
||||
// возвращаем все задачи конкретного проекта
|
||||
projectsList := TasksList{tasks}
|
||||
jsonGoodResponse, _ := json.Marshal(projectsList)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(jsonGoodResponse)
|
||||
}
|
||||
|
||||
func addTask(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
var task db.Task
|
||||
reqBody, err := io.ReadAll(r.Body)
|
||||
if err == nil {
|
||||
json.Unmarshal(reqBody, &task)
|
||||
if task.Name == "" || task.ProjectID == 0 {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
task.ID = 0
|
||||
task, err := repository.AddTask(task)
|
||||
if err != nil {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
goodResponse := GoodResponse{
|
||||
Code: 201,
|
||||
Message: "Задача создана",
|
||||
ID: task.ID,
|
||||
}
|
||||
jsonGoodResponse, _ := json.Marshal(goodResponse)
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write(jsonGoodResponse)
|
||||
return
|
||||
}
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
}
|
||||
|
||||
func doneTask(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
|
||||
queryStr := r.URL.Query()
|
||||
|
||||
idStr, ok := queryStr["id"]
|
||||
if !ok {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
if len(idStr) == 0 {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(idStr[0])
|
||||
if err != nil {
|
||||
errorResponse(w, ErrorResponse{http.StatusBadRequest,
|
||||
"Validation Failed"})
|
||||
return
|
||||
}
|
||||
|
||||
err = repository.TaskDone(id)
|
||||
if err != nil {
|
||||
errorResponse(w, ErrorResponse{http.StatusNotFound,
|
||||
"Tasks not found"})
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
23
part_10/10.4/golang/todo-service/service/logger.go
Normal file
23
part_10/10.4/golang/todo-service/service/logger.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Logger(inner http.Handler, name string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
|
||||
inner.ServeHTTP(w, r)
|
||||
|
||||
log.Printf(
|
||||
"%s %s %s %s",
|
||||
r.Method,
|
||||
r.RequestURI,
|
||||
name,
|
||||
time.Since(start),
|
||||
)
|
||||
})
|
||||
}
|
||||
102
part_10/10.4/golang/todo-service/service/routers.go
Normal file
102
part_10/10.4/golang/todo-service/service/routers.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"golang/todo-service/db"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type Route struct {
|
||||
Name string // имя функции обработчика
|
||||
Method string // тип HTTP-сообщения
|
||||
Pattern string // шаблон пути
|
||||
HandlerFunc http.HandlerFunc // ссылка на функцию обработчик
|
||||
// сигнатура функции должна быть func(ResponseWriter, *Request)
|
||||
}
|
||||
|
||||
var repository *db.SQLiteRepository
|
||||
|
||||
func NewRouter(rep *db.SQLiteRepository) *mux.Router {
|
||||
repository = rep
|
||||
router := mux.NewRouter().StrictSlash(true)
|
||||
for _, route := range routes {
|
||||
var handler http.Handler
|
||||
handler = route.HandlerFunc
|
||||
//оборачиваем функцию-обработчик в логгер
|
||||
handler = Logger(route.HandlerFunc, route.Name)
|
||||
// handler := route.HandlerFunc
|
||||
// // // добавляем новый обработчик
|
||||
router. //HandleFunc(route.Pattern, handler).Methods(route.Method)
|
||||
Methods(route.Method). // тип HTTP-сообщения
|
||||
Path(route.Pattern). // шаблон пути
|
||||
Name(route.Name). // имя функции обработчика
|
||||
Handler(handler) // ссылка на функцию обработчик
|
||||
}
|
||||
router.Use(mux.CORSMethodMiddleware(router))
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
func home(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hello Wold in REST API style!!!")
|
||||
}
|
||||
|
||||
var routes = []Route{
|
||||
{ // домашняя страница
|
||||
"home",
|
||||
http.MethodGet,
|
||||
"/api/v1/todo",
|
||||
home,
|
||||
},
|
||||
{ // удаление проекта по id
|
||||
"deleteProject",
|
||||
http.MethodDelete,
|
||||
"/api/v1/todo/project/del/{id}",
|
||||
deleteProject,
|
||||
},
|
||||
{ // добавление проекта
|
||||
"addProject",
|
||||
http.MethodPost,
|
||||
"/api/v1/todo/project",
|
||||
addProject,
|
||||
},
|
||||
{ // получить все проекты
|
||||
"getProjects",
|
||||
http.MethodGet,
|
||||
"/api/v1/todo/projects",
|
||||
getProjects,
|
||||
},
|
||||
{ // удаление задачи
|
||||
"deleteTask",
|
||||
http.MethodDelete,
|
||||
"/api/v1/todo/task",
|
||||
deleteTask,
|
||||
},
|
||||
{ // получение всех задач или конкретного проекта
|
||||
"getTask",
|
||||
http.MethodGet,
|
||||
"/api/v1/todo/task",
|
||||
getTask,
|
||||
},
|
||||
{ // добавить задачу
|
||||
"addTask",
|
||||
http.MethodPost,
|
||||
"/api/v1/todo/task",
|
||||
addTask,
|
||||
},
|
||||
{ // изменение статуса задачи на «Выполнено»
|
||||
"doneTask",
|
||||
http.MethodPut,
|
||||
"/api/v1/todo/task",
|
||||
doneTask,
|
||||
},
|
||||
}
|
||||
|
||||
func errorResponse(w http.ResponseWriter, err ErrorResponse) {
|
||||
jsonResponse, _ := json.Marshal(err)
|
||||
w.WriteHeader(err.Code)
|
||||
w.Write(jsonResponse)
|
||||
}
|
||||
429
part_10/10.4/golang/todo-service/todo-service-api.yml
Normal file
429
part_10/10.4/golang/todo-service/todo-service-api.yml
Normal file
@@ -0,0 +1,429 @@
|
||||
openapi: 3.0.2
|
||||
info:
|
||||
title: ToDo client-server api
|
||||
description: |
|
||||
Документация по описанию конечных точек сервера, посредством которых
|
||||
происходит доступ к ресурсам
|
||||
version: 1.0.0
|
||||
servers:
|
||||
- url: http://127.0.0.1:8080/api/v1/todo
|
||||
|
||||
tags:
|
||||
- name: task
|
||||
- name: project
|
||||
|
||||
paths:
|
||||
/project:
|
||||
post:
|
||||
tags:
|
||||
- project
|
||||
description: |
|
||||
Добавление проекта
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Project'
|
||||
responses:
|
||||
"201":
|
||||
description: Добавление прошло успешно.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GoodResponse'
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 201,
|
||||
"message": "Project created",
|
||||
"id": 1
|
||||
}
|
||||
"400":
|
||||
description: Невалидная схема проекта или входные данные не верны.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 400,
|
||||
"message": "Validation Failed"
|
||||
}
|
||||
|
||||
/project/del/{id}:
|
||||
delete:
|
||||
tags:
|
||||
- project
|
||||
description: |
|
||||
Удалить проект
|
||||
parameters:
|
||||
- description: Идентификатор
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
example: 1
|
||||
responses:
|
||||
"200":
|
||||
description: Удаление прошло успешно.
|
||||
"400":
|
||||
description: Невалидная схема проекта или входные данные не верны.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 400,
|
||||
"message": "Validation Failed"
|
||||
}
|
||||
"404":
|
||||
description: Проект не найден.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 404,
|
||||
"message": "Project not found"
|
||||
}
|
||||
|
||||
/projects:
|
||||
get:
|
||||
tags:
|
||||
- project
|
||||
description: |
|
||||
Получить список проектов
|
||||
responses:
|
||||
"200":
|
||||
description: Запрос прошел успешно
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProgectsList"
|
||||
"404":
|
||||
description: Проект не найден.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 404,
|
||||
"message": "Projects not found"
|
||||
}
|
||||
|
||||
/task:
|
||||
put:
|
||||
tags:
|
||||
- task
|
||||
description: |
|
||||
Изменение статуса задачи
|
||||
parameters:
|
||||
- in: query
|
||||
required: true
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
example: 1
|
||||
responses:
|
||||
"201":
|
||||
description: Запрос прошел успешно
|
||||
"400":
|
||||
description: Невалидная схема задачи или входные данные не верны.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 400,
|
||||
"message": "Validation Failed"
|
||||
}
|
||||
"404":
|
||||
description: Проект не найден.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 404,
|
||||
"message": "Tasks not found"
|
||||
}
|
||||
post:
|
||||
tags:
|
||||
- task
|
||||
description: |
|
||||
Добавление задачи
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Task"
|
||||
responses:
|
||||
"201":
|
||||
description: Добавление прошло успешно.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/GoodResponse"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 201,
|
||||
"message": "Task created",
|
||||
"id": 1
|
||||
}
|
||||
"400":
|
||||
description: Невалидная схема задачи или входные данные не верны.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 400,
|
||||
"message": "Validation Failed"
|
||||
}
|
||||
get:
|
||||
tags:
|
||||
- task
|
||||
description: |
|
||||
Получение списка всех задач или конкретного проекта
|
||||
parameters:
|
||||
- in: query
|
||||
name: projectID
|
||||
schema:
|
||||
type: integer
|
||||
example: 1
|
||||
responses:
|
||||
"200":
|
||||
description: Запрос прошел успешно
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/TasksList"
|
||||
"400":
|
||||
description: Невалидная схема задачи или входные данные не верны.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 400,
|
||||
"message": "Validation Failed"
|
||||
}
|
||||
"404":
|
||||
description: Проект не найден.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 404,
|
||||
"message": "Tasks not found"
|
||||
}
|
||||
delete:
|
||||
tags:
|
||||
- task
|
||||
description: |
|
||||
Удаление задачи с заданным ID
|
||||
parameters:
|
||||
- in: query
|
||||
required: true
|
||||
name: id
|
||||
schema:
|
||||
type: integer
|
||||
example: 1
|
||||
responses:
|
||||
"200":
|
||||
description: Запрос прошел успешно
|
||||
"400":
|
||||
description: Невалидная схема задачи или входные данные не верны.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 400,
|
||||
"message": "Validation Failed"
|
||||
}
|
||||
"404":
|
||||
description: Задача не найдена.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
response:
|
||||
value: |-
|
||||
{
|
||||
"code": 404,
|
||||
"message": "Task not found"
|
||||
}
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Error:
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
nullable: false
|
||||
message:
|
||||
type: string
|
||||
nullable: false
|
||||
|
||||
GoodResponse:
|
||||
required:
|
||||
- code
|
||||
- id
|
||||
- message
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
nullable: false
|
||||
message:
|
||||
type: string
|
||||
nullable: false
|
||||
id:
|
||||
type: integer
|
||||
nullable: false
|
||||
example:
|
||||
code: 0
|
||||
id: 6
|
||||
message: message
|
||||
|
||||
Project:
|
||||
required:
|
||||
- description
|
||||
- id
|
||||
- name
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
description: id project
|
||||
name:
|
||||
type: string
|
||||
description: Имя проекта
|
||||
nullable: false
|
||||
description:
|
||||
type: string
|
||||
description: Описание проекта
|
||||
nullable: false
|
||||
example:
|
||||
id: 1
|
||||
name: Пафос и Превозмогание
|
||||
description: Прожать батоны и вперед!!!
|
||||
|
||||
ProgectsList:
|
||||
type: object
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
description: Список существующих проектов
|
||||
nullable: false
|
||||
items:
|
||||
$ref: '#/components/schemas/Project'
|
||||
example:
|
||||
items:
|
||||
- id: 1
|
||||
name: Пафос и Превозмогание
|
||||
description: Прожать батоны и вперед!!!
|
||||
- id: 1
|
||||
name: Пафос и Превозмогание
|
||||
description: Прожать батоны и вперед!!!
|
||||
|
||||
Task:
|
||||
required:
|
||||
- description
|
||||
- id
|
||||
- isDone
|
||||
- name
|
||||
- projectID
|
||||
- priority
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
description: id task
|
||||
name:
|
||||
type: string
|
||||
description: Имя задачи
|
||||
nullable: false
|
||||
description:
|
||||
type: string
|
||||
description: Описание задачи
|
||||
nullable: false
|
||||
priority:
|
||||
type: integer
|
||||
description: приоритет задачи
|
||||
nullable: false
|
||||
isDone:
|
||||
type: boolean
|
||||
description: Флаг о выполнении задачи
|
||||
nullable: false
|
||||
projectID:
|
||||
type: integer
|
||||
description: id task
|
||||
nullable: false
|
||||
example:
|
||||
id: 1
|
||||
name: 10к подписчиков
|
||||
description: Прожать батоны и вперед!!!
|
||||
isDone: false
|
||||
projectID: 1
|
||||
priority: 3
|
||||
|
||||
TasksList:
|
||||
type: object
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
description: Список существующих проектов
|
||||
nullable: false
|
||||
items:
|
||||
$ref: '#/components/schemas/Task'
|
||||
example:
|
||||
items:
|
||||
- id: 1
|
||||
name: 10к подписчиков
|
||||
description: Прожать батоны и вперед!!!
|
||||
isDone: false
|
||||
projectID: 1
|
||||
- id: 1
|
||||
name: 10к подписчиков
|
||||
description: Прожать батоны и вперед!!!
|
||||
isDone: false
|
||||
projectID: 1
|
||||
BIN
part_10/10.4/golang/todo-service/todo.db
Normal file
BIN
part_10/10.4/golang/todo-service/todo.db
Normal file
Binary file not shown.
19
part_11/11.1/golang/testing/calculator/calculator.go
Normal file
19
part_11/11.1/golang/testing/calculator/calculator.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package calculator
|
||||
|
||||
import "math"
|
||||
|
||||
func Add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func Sub(a, b int) int {
|
||||
return a - b
|
||||
}
|
||||
|
||||
func Mul(a, b int) int {
|
||||
return a * b
|
||||
}
|
||||
|
||||
func Pow2(a int) int {
|
||||
return int(math.Pow(float64(a), 2))
|
||||
}
|
||||
3
part_11/11.1/golang/testing/go.mod
Normal file
3
part_11/11.1/golang/testing/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module golang/testing
|
||||
|
||||
go 1.19
|
||||
13
part_11/11.1/golang/testing/main.go
Normal file
13
part_11/11.1/golang/testing/main.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
calc "golang/testing/calculator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(calc.Add(4, 2)) // 6
|
||||
fmt.Println(calc.Sub(23, 12)) // 11
|
||||
fmt.Println(calc.Mul(5, 6)) // 30
|
||||
fmt.Println(calc.Pow2(5)) // 25
|
||||
}
|
||||
38
part_11/11.1/golang/testing/test/calculator_test.go
Normal file
38
part_11/11.1/golang/testing/test/calculator_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package test_test
|
||||
|
||||
import (
|
||||
calc "golang/testing/calculator"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAdd(t *testing.T) {
|
||||
result := calc.Add(2, 5)
|
||||
expected := 7
|
||||
if result != expected {
|
||||
t.Errorf("result %d, expected %d", result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSub(t *testing.T) {
|
||||
result := calc.Sub(15, 5)
|
||||
expected := 10
|
||||
if result != expected {
|
||||
t.Errorf("result %d, expected %d", result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMul(t *testing.T) {
|
||||
result := calc.Mul(3, 6)
|
||||
expected := 18
|
||||
if result != expected {
|
||||
t.Errorf("result %d, expected %d", result, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPow2(t *testing.T) {
|
||||
result := calc.Pow2(3)
|
||||
expected := 9
|
||||
if result != expected {
|
||||
t.Errorf("result %d, expected %d", result, expected)
|
||||
}
|
||||
}
|
||||
19
part_11/11.2/golang/testing/calculator/calculator.go
Normal file
19
part_11/11.2/golang/testing/calculator/calculator.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package calculator
|
||||
|
||||
import "math"
|
||||
|
||||
func Add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func Sub(a, b int) int {
|
||||
return a - b
|
||||
}
|
||||
|
||||
func Mul(a, b int) int {
|
||||
return a * b
|
||||
}
|
||||
|
||||
func Pow2(a int) int {
|
||||
return int(math.Pow(float64(a), 2))
|
||||
}
|
||||
3
part_11/11.2/golang/testing/go.mod
Normal file
3
part_11/11.2/golang/testing/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module golang/testing
|
||||
|
||||
go 1.19
|
||||
13
part_11/11.2/golang/testing/main.go
Normal file
13
part_11/11.2/golang/testing/main.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
calc "golang/testing/calculator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(calc.Add(4, 2)) // 6
|
||||
fmt.Println(calc.Sub(23, 12)) // 11
|
||||
fmt.Println(calc.Mul(5, 6)) // 30
|
||||
fmt.Println(calc.Pow2(5)) // 25
|
||||
}
|
||||
70
part_11/11.2/golang/testing/test/calculator_test.go
Normal file
70
part_11/11.2/golang/testing/test/calculator_test.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package test_test
|
||||
|
||||
import (
|
||||
calc "golang/testing/calculator"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testData struct {
|
||||
arg1, arg2, expected int
|
||||
}
|
||||
|
||||
type testPowData struct {
|
||||
arg, expected int
|
||||
}
|
||||
|
||||
func TestAdd(t *testing.T) {
|
||||
cases := []testData{
|
||||
{2, 3, 5},
|
||||
{10, 5, 15},
|
||||
{-8, -3, -11},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := calc.Add(it.arg1, it.arg2)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSub(t *testing.T) {
|
||||
cases := []testData{
|
||||
{2, 3, -1},
|
||||
{10, 5, 5},
|
||||
{-8, -3, -5},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := calc.Sub(it.arg1, it.arg2)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMul(t *testing.T) {
|
||||
cases := []testData{
|
||||
{2, 3, 6},
|
||||
{10, 5, 50},
|
||||
{-8, -3, 24},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := calc.Mul(it.arg1, it.arg2)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPow2(t *testing.T) {
|
||||
cases := []testPowData{
|
||||
{2, 4},
|
||||
{-2, 4},
|
||||
{3, 9},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := calc.Pow2(it.arg)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
19
part_11/11.3/golang/testing/calculator/calculator.go
Normal file
19
part_11/11.3/golang/testing/calculator/calculator.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package calculator
|
||||
|
||||
import "math"
|
||||
|
||||
func Add(a, b int) int {
|
||||
return a + b + 1
|
||||
}
|
||||
|
||||
func Sub(a, b int) int {
|
||||
return a - b
|
||||
}
|
||||
|
||||
func Mul(a, b int) int {
|
||||
return a * b
|
||||
}
|
||||
|
||||
func Pow2(a int) int {
|
||||
return int(math.Pow(float64(a), 2))
|
||||
}
|
||||
3
part_11/11.3/golang/testing/go.mod
Normal file
3
part_11/11.3/golang/testing/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module golang/testing
|
||||
|
||||
go 1.19
|
||||
13
part_11/11.3/golang/testing/main.go
Normal file
13
part_11/11.3/golang/testing/main.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
calc "golang/testing/calculator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(calc.Add(4, 2)) // 6
|
||||
fmt.Println(calc.Sub(23, 12)) // 11
|
||||
fmt.Println(calc.Mul(5, 6)) // 30
|
||||
fmt.Println(calc.Pow2(5)) // 25
|
||||
}
|
||||
76
part_11/11.3/golang/testing/test/calculator_test.go
Normal file
76
part_11/11.3/golang/testing/test/calculator_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package test_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
calc "golang/testing/calculator"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testData struct {
|
||||
arg1, arg2, expected int
|
||||
}
|
||||
|
||||
type testPowData struct {
|
||||
arg, expected int
|
||||
}
|
||||
|
||||
func TestAdd(t *testing.T) {
|
||||
cases := []testData{
|
||||
{2, 3, 5},
|
||||
{10, 5, 15},
|
||||
{-8, -3, -11},
|
||||
}
|
||||
for _, it := range cases {
|
||||
t.Run(
|
||||
fmt.Sprintf("%d+%d=%d", it.arg1, it.arg2, it.expected), // имя подтеста
|
||||
func(t *testing.T) { // подтест
|
||||
result := calc.Add(it.arg1, it.arg2)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSub(t *testing.T) {
|
||||
cases := []testData{
|
||||
{2, 3, -1},
|
||||
{10, 5, 5},
|
||||
{-8, -3, -5},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := calc.Sub(it.arg1, it.arg2)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMul(t *testing.T) {
|
||||
cases := []testData{
|
||||
{2, 3, 6},
|
||||
{10, 5, 50},
|
||||
{-8, -3, 24},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := calc.Mul(it.arg1, it.arg2)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPow2(t *testing.T) {
|
||||
cases := []testPowData{
|
||||
{2, 4},
|
||||
{-2, 4},
|
||||
{3, 9},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := calc.Pow2(it.arg)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
19
part_11/11.4/golang/testing/calculator/calculator.go
Normal file
19
part_11/11.4/golang/testing/calculator/calculator.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package calculator
|
||||
|
||||
import "math"
|
||||
|
||||
func Add(a, b int) int {
|
||||
return a + b + 1
|
||||
}
|
||||
|
||||
func Sub(a, b int) int {
|
||||
return a - b
|
||||
}
|
||||
|
||||
func Mul(a, b int) int {
|
||||
return a * b
|
||||
}
|
||||
|
||||
func Pow2(a int) int {
|
||||
return int(math.Pow(float64(a), 2))
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package calculator
|
||||
|
||||
import "testing"
|
||||
|
||||
func BenchmarkMul(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Mul(5, 10)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPow2(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Pow2(5)
|
||||
}
|
||||
}
|
||||
41
part_11/11.4/golang/testing/calculator/calculator_test.go
Normal file
41
part_11/11.4/golang/testing/calculator/calculator_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package calculator
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testData struct {
|
||||
arg1, arg2, expected int
|
||||
}
|
||||
|
||||
type testPowData struct {
|
||||
arg, expected int
|
||||
}
|
||||
|
||||
func TestSub(t *testing.T) {
|
||||
cases := []testData{
|
||||
{2, 3, -1},
|
||||
{10, 5, 5},
|
||||
{-8, -3, -5},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := Sub(it.arg1, it.arg2)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPow2(t *testing.T) {
|
||||
cases := []testPowData{
|
||||
{2, 4},
|
||||
{-2, 4},
|
||||
{3, 9},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := Pow2(it.arg)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
3
part_11/11.4/golang/testing/go.mod
Normal file
3
part_11/11.4/golang/testing/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module golang/testing
|
||||
|
||||
go 1.19
|
||||
13
part_11/11.4/golang/testing/main.go
Normal file
13
part_11/11.4/golang/testing/main.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
calc "golang/testing/calculator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(calc.Add(4, 2)) // 6
|
||||
fmt.Println(calc.Sub(23, 12)) // 11
|
||||
fmt.Println(calc.Mul(5, 6)) // 30
|
||||
fmt.Println(calc.Pow2(5)) // 25
|
||||
}
|
||||
19
part_11/11.5/golang/testing/calculator/calculator.go
Normal file
19
part_11/11.5/golang/testing/calculator/calculator.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package calculator
|
||||
|
||||
import "math"
|
||||
|
||||
func Add(a, b int) int {
|
||||
return a + b + 1
|
||||
}
|
||||
|
||||
func Sub(a, b int) int {
|
||||
return a - b
|
||||
}
|
||||
|
||||
func Mul(a, b int) int {
|
||||
return a * b
|
||||
}
|
||||
|
||||
func Pow2(a int) int {
|
||||
return int(math.Pow(float64(a), 2))
|
||||
}
|
||||
41
part_11/11.5/golang/testing/calculator/calculator_test.go
Normal file
41
part_11/11.5/golang/testing/calculator/calculator_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package calculator
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testData struct {
|
||||
arg1, arg2, expected int
|
||||
}
|
||||
|
||||
type testPowData struct {
|
||||
arg, expected int
|
||||
}
|
||||
|
||||
func TestSub(t *testing.T) {
|
||||
cases := []testData{
|
||||
{2, 3, -1},
|
||||
{10, 5, 5},
|
||||
{-8, -3, -5},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := Sub(it.arg1, it.arg2)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPow2(t *testing.T) {
|
||||
cases := []testPowData{
|
||||
{2, 4},
|
||||
{-2, 4},
|
||||
{3, 9},
|
||||
}
|
||||
for _, it := range cases {
|
||||
result := Pow2(it.arg)
|
||||
if result != it.expected {
|
||||
t.Errorf("result %d, expected %d", result, it.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
3
part_11/11.5/golang/testing/go.mod
Normal file
3
part_11/11.5/golang/testing/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module golang/testing
|
||||
|
||||
go 1.19
|
||||
13
part_11/11.5/golang/testing/main.go
Normal file
13
part_11/11.5/golang/testing/main.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
calc "golang/testing/calculator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(calc.Add(4, 2)) // 6
|
||||
fmt.Println(calc.Sub(23, 12)) // 11
|
||||
fmt.Println(calc.Mul(5, 6)) // 30
|
||||
fmt.Println(calc.Pow2(5)) // 25
|
||||
}
|
||||
36
part_11/11.6/1.go
Normal file
36
part_11/11.6/1.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jaswdr/faker"
|
||||
)
|
||||
|
||||
func main() {
|
||||
faker := faker.New()
|
||||
|
||||
fmt.Println("----------Names----------")
|
||||
for i := 0; i < 3; i++ {
|
||||
fmt.Println(faker.Person().Name())
|
||||
}
|
||||
fmt.Println("----------Beer----------")
|
||||
for i := 0; i < 3; i++ {
|
||||
fmt.Println(faker.Beer().Name())
|
||||
}
|
||||
fmt.Println("----------Address----------")
|
||||
for i := 0; i < 3; i++ {
|
||||
fmt.Println(faker.Address().Address())
|
||||
}
|
||||
fmt.Println("----------Country----------")
|
||||
for i := 0; i < 3; i++ {
|
||||
fmt.Println(faker.Address().Country())
|
||||
}
|
||||
fmt.Println("----------Email----------")
|
||||
for i := 0; i < 3; i++ {
|
||||
fmt.Println(faker.Internet().Email())
|
||||
}
|
||||
fmt.Println("-----Phone Number--------")
|
||||
for i := 0; i < 3; i++ {
|
||||
fmt.Println(faker.Phone().Number())
|
||||
}
|
||||
}
|
||||
14
part_2/2.5.1/1.go
Normal file
14
part_2/2.5.1/1.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
t := 20
|
||||
if t >= 30 {
|
||||
fmt.Println("Надеть шорты")
|
||||
} else {
|
||||
fmt.Println("Надеть брюки")
|
||||
}
|
||||
}
|
||||
|
||||
// Надеть брюки
|
||||
13
part_2/2.5.1/2.go
Normal file
13
part_2/2.5.1/2.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
sun := true // поменяйте на false и снова запустите приложение
|
||||
if !sun {
|
||||
fmt.Println("Взять зонт")
|
||||
}
|
||||
fmt.Println("Выйти на улицу")
|
||||
}
|
||||
|
||||
// Выйти на улицу
|
||||
18
part_2/2.5.1/3.go
Normal file
18
part_2/2.5.1/3.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
var value int = 15
|
||||
if value > 0 && value < 10 {
|
||||
fmt.Println("Число входит в диапазон от 0 до 10")
|
||||
} else if value > 10 && value < 20 {
|
||||
fmt.Println("Число входит в диапазон от 10 до 20")
|
||||
} else if value > 20 && value < 30 {
|
||||
fmt.Println("Число входит в диапазон от 20 до 30")
|
||||
} else {
|
||||
fmt.Println("Значение > 30")
|
||||
}
|
||||
}
|
||||
|
||||
// Число входит в диапазон от 10 до 20
|
||||
22
part_2/2.5.1/4.go
Normal file
22
part_2/2.5.1/4.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
var value int = 15
|
||||
if value > 30 {
|
||||
if value < 50 {
|
||||
fmt.Println("30 < value < 50")
|
||||
} else {
|
||||
fmt.Println("30 < value >= 50")
|
||||
}
|
||||
} else {
|
||||
if value > 10 {
|
||||
fmt.Println("30 >= value >= 10")
|
||||
} else {
|
||||
fmt.Println("30 >= value < 10")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 30 >= value >= 10
|
||||
13
part_2/2.5.1/5.go
Normal file
13
part_2/2.5.1/5.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
if value := 15; value > 30 {
|
||||
fmt.Println("30 < value")
|
||||
} else {
|
||||
fmt.Println("30 >= value")
|
||||
}
|
||||
}
|
||||
|
||||
// 30 >= value
|
||||
19
part_2/2.5.2/1.go
Normal file
19
part_2/2.5.2/1.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
value := 2
|
||||
switch value {
|
||||
case 2:
|
||||
fmt.Println("2")
|
||||
fmt.Printf("%d + 2 = %d", value, value+2)
|
||||
case 4:
|
||||
fmt.Println("4")
|
||||
default:
|
||||
fmt.Println("8")
|
||||
}
|
||||
}
|
||||
|
||||
// 2
|
||||
// 2 + 2 = 4
|
||||
20
part_2/2.5.2/2.go
Normal file
20
part_2/2.5.2/2.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
value := 2
|
||||
switch value := 4; value {
|
||||
case 2:
|
||||
fmt.Println("2")
|
||||
fmt.Printf("%d + 2 = %d", value, value+2)
|
||||
case 4:
|
||||
fmt.Println("4")
|
||||
default:
|
||||
fmt.Println("8")
|
||||
}
|
||||
fmt.Printf("value = %d", value)
|
||||
}
|
||||
|
||||
// 4
|
||||
// value = 2
|
||||
15
part_2/2.5.2/3.go
Normal file
15
part_2/2.5.2/3.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
name := "Alex"
|
||||
switch name {
|
||||
case "Stanislav":
|
||||
fmt.Println("Admin")
|
||||
case "Maxim", "Alex", "Bill":
|
||||
fmt.Println("Employee")
|
||||
}
|
||||
}
|
||||
|
||||
// Employee
|
||||
17
part_2/2.5.2/4.go
Normal file
17
part_2/2.5.2/4.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
name := "Stanislav"
|
||||
switch name {
|
||||
case "Stanislav":
|
||||
fmt.Println("Admin")
|
||||
fallthrough
|
||||
case "Maxim", "Alex", "Bill":
|
||||
fmt.Println("Employee")
|
||||
}
|
||||
}
|
||||
|
||||
// Admin
|
||||
// Employee
|
||||
17
part_2/2.5.2/5.go
Normal file
17
part_2/2.5.2/5.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
name := "Stanislav"
|
||||
switch name {
|
||||
case "Stanislav":
|
||||
fmt.Println("Admin")
|
||||
break
|
||||
fallthrough
|
||||
case "Maxim", "Alex", "Bill":
|
||||
fmt.Println("Employee")
|
||||
}
|
||||
}
|
||||
|
||||
// Admin
|
||||
25
part_2/2.5.2/6.go
Normal file
25
part_2/2.5.2/6.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
var value int = 5
|
||||
switch {
|
||||
case value > 30:
|
||||
switch {
|
||||
case value < 50:
|
||||
fmt.Println("30 < value < 50")
|
||||
default:
|
||||
fmt.Println("30 < value >= 50")
|
||||
}
|
||||
case value < 30:
|
||||
switch {
|
||||
case value > 10:
|
||||
fmt.Println("30 >= value >= 10")
|
||||
default:
|
||||
fmt.Println("30 >= value < 10")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 30 >= value < 10
|
||||
10
part_2/2.6/1.go
Normal file
10
part_2/2.6/1.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
value := 2
|
||||
for i := 0; i < 10; i++ {
|
||||
fmt.Printf("%d * %d = %d\n", value, i, value*i)
|
||||
}
|
||||
}
|
||||
19
part_2/2.6/2.go
Normal file
19
part_2/2.6/2.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := ""
|
||||
i := 0
|
||||
for {
|
||||
str += strconv.Itoa(i)
|
||||
if i >= 5 {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
fmt.Println(str) // 012345
|
||||
}
|
||||
16
part_2/2.6/3.go
Normal file
16
part_2/2.6/3.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
str := ""
|
||||
i := 0
|
||||
for i <= 5 {
|
||||
str += strconv.Itoa(i)
|
||||
i++
|
||||
}
|
||||
fmt.Println(str) // 012345
|
||||
}
|
||||
14
part_2/2.6/4.go
Normal file
14
part_2/2.6/4.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
i := 13
|
||||
for i > 0 {
|
||||
i--
|
||||
if i%2 == 0 {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("%d ", i)
|
||||
}
|
||||
}
|
||||
27
part_2/2.6/5.go
Normal file
27
part_2/2.6/5.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
for i := 0; i < 2; i++ {
|
||||
for j := 0; j < 3; j++ {
|
||||
if i == j {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("%d %d || ", i, j)
|
||||
}
|
||||
}
|
||||
// 0 1 || 0 2 || 1 0 || 1 2 ||
|
||||
|
||||
fmt.Println()
|
||||
for i := 0; i < 2; i++ {
|
||||
for j := 0; j < 3; j++ {
|
||||
if i == j {
|
||||
break
|
||||
}
|
||||
fmt.Printf("%d %d || ", i, j)
|
||||
}
|
||||
}
|
||||
fmt.Println("Oo")
|
||||
// 1 0 || Oo
|
||||
}
|
||||
11
part_2/2.6/6.go
Normal file
11
part_2/2.6/6.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
array := [4]int{2, 5, 6, 0}
|
||||
for i := 0; i < len(array); i++ {
|
||||
array[i] += 3
|
||||
fmt.Printf("%d ", array[i])
|
||||
}
|
||||
}
|
||||
14
part_2/2.6/7.go
Normal file
14
part_2/2.6/7.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
array := [4]int{2, 5, 6, 0}
|
||||
for i, v := range array {
|
||||
v += 3
|
||||
fmt.Printf("%d) %d || ", i, v)
|
||||
}
|
||||
// 0) 5 || 1) 8 || 2) 9 || 3) 3 ||
|
||||
fmt.Println()
|
||||
fmt.Println(array) // [2 5 6 0]
|
||||
}
|
||||
11
part_2/2.6/8.go
Normal file
11
part_2/2.6/8.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
array := [4]int{2, 5, 6, 0}
|
||||
for i := range array {
|
||||
array[i] += 3
|
||||
}
|
||||
fmt.Println(array) // [5 8 9 3]
|
||||
}
|
||||
15
part_2/2.6/9.go
Normal file
15
part_2/2.6/9.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
myMap := map[int]string{
|
||||
1: "Alex",
|
||||
2: "Maxim",
|
||||
200: "Jon",
|
||||
}
|
||||
|
||||
for i, v := range myMap {
|
||||
fmt.Printf("key = %d, value = %s\n", i, v)
|
||||
}
|
||||
}
|
||||
11
part_2/2.7/1.go
Normal file
11
part_2/2.7/1.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(1) // 1
|
||||
goto myLable
|
||||
fmt.Println(2)
|
||||
myLable: // метка для безусловного перехода
|
||||
fmt.Println(3) // 3
|
||||
}
|
||||
16
part_2/2.7/2.go
Normal file
16
part_2/2.7/2.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
test()
|
||||
fmt.Println(1)
|
||||
goto myLable
|
||||
fmt.Println(2)
|
||||
myLable:
|
||||
fmt.Println(3)
|
||||
}
|
||||
|
||||
func test() {
|
||||
goto myLable // error: label myLable not defined
|
||||
}
|
||||
10
part_2/2.7/3.go
Normal file
10
part_2/2.7/3.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
myLable: // бесконечный цикл
|
||||
fmt.Println(1)
|
||||
goto myLable
|
||||
fmt.Println(2)
|
||||
}
|
||||
15
part_3/3.1/1.go
Normal file
15
part_3/3.1/1.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
hello() // вызов функции hello
|
||||
fmt.Println("exit")
|
||||
}
|
||||
|
||||
func hello() {
|
||||
fmt.Println("Hello World!")
|
||||
}
|
||||
|
||||
// Hello World!
|
||||
// exit
|
||||
15
part_3/3.1/2.go
Normal file
15
part_3/3.1/2.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
add(3, 5)
|
||||
}
|
||||
|
||||
func add(a int, b int) {
|
||||
fmt.Println(a + b) // 8
|
||||
}
|
||||
|
||||
// func add(a, b int) {
|
||||
// fmt.Println(a + b)
|
||||
// }
|
||||
13
part_3/3.1/3.go
Normal file
13
part_3/3.1/3.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
userInfo(3, 5, "Alex")
|
||||
}
|
||||
|
||||
func userInfo(age, exp int, name string) {
|
||||
fmt.Printf("User name: %s, age: %d, exp years: %d", name, age, exp)
|
||||
}
|
||||
|
||||
// User name: Alex, age: 3, exp years: 5
|
||||
11
part_3/3.1/4.go
Normal file
11
part_3/3.1/4.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println(userInfo(3, 5, "Alex")) // User name: Alex, age: 3, exp years: 5
|
||||
}
|
||||
|
||||
func userInfo(age, exp int, name string) string {
|
||||
return fmt.Sprintf("User name: %s, age: %d, exp year: %d", name, age, exp)
|
||||
}
|
||||
24
part_3/3.1/5.go
Normal file
24
part_3/3.1/5.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
rez, check := add(10, 8)
|
||||
fmt.Printf("a + b = %d, a > b = %t", rez, check)
|
||||
}
|
||||
|
||||
func add(a, b int) (int, bool) {
|
||||
return a + b, a > b
|
||||
}
|
||||
|
||||
// a + b = 18, a > b = true
|
||||
|
||||
// func main() {
|
||||
// rez := add(10, 8) // assignment mismatch: 1 variable but add returns 2 values
|
||||
// fmt.Printf("a + b = %d", rez)
|
||||
// }
|
||||
|
||||
// func main() {
|
||||
// rez, _ := add(10, 8)
|
||||
// fmt.Printf("a + b = %d", rez) // a + b = 18
|
||||
// }
|
||||
17
part_3/3.1/6.go
Normal file
17
part_3/3.1/6.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
rez, check := add(10, 8)
|
||||
fmt.Printf("a + b = %d, a > b = %t", rez, check)
|
||||
}
|
||||
|
||||
func add(a, b int) (rez int, check bool) {
|
||||
rez = a + b
|
||||
check = a > b
|
||||
return // аналогично return rez, check
|
||||
|
||||
}
|
||||
|
||||
// a + b = 18, a > b = true
|
||||
17
part_3/3.1/7.go
Normal file
17
part_3/3.1/7.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Sum = %d", myFunc(3, 5, 9, 25, -10))
|
||||
}
|
||||
|
||||
func myFunc(values ...int) (sum int) {
|
||||
// переменную values рассматриваем как срез []int
|
||||
for _, value := range values {
|
||||
sum += value
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Sum = 32
|
||||
14
part_3/3.1/8.go
Normal file
14
part_3/3.1/8.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
sum := func(values ...int) (sum int) { // объявление функции
|
||||
// переменную values рассматриваем как срез []int
|
||||
for _, value := range values {
|
||||
sum += value
|
||||
}
|
||||
return
|
||||
}(3, 5, 9, 25, -10) // вызов функции
|
||||
fmt.Printf("Sum = %d", sum) // Sum = 32
|
||||
}
|
||||
34
part_3/3.1/9.go
Normal file
34
part_3/3.1/9.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
// генератор случайных чисел
|
||||
var generator = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
func sliceCreator1(size int16) (slice *[]int16) {
|
||||
slice = new([]int16)
|
||||
*slice = make([]int16, size, size+10)
|
||||
for i := range *slice {
|
||||
(*slice)[i] += int16(generator.Int())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func sliceCreator2(size int16) *[]int16 {
|
||||
slice := make([]int16, size, size+10)
|
||||
for i := range slice {
|
||||
slice[i] += int16(generator.Int())
|
||||
}
|
||||
return &slice
|
||||
}
|
||||
|
||||
func main() {
|
||||
slice := sliceCreator1(7)
|
||||
fmt.Println(*slice) // [-22201 -30245 6682 28346 23159 -28589 16762]
|
||||
slice = sliceCreator2(5)
|
||||
fmt.Println(*slice) // [3896 28732 -30834 1722 -14725]
|
||||
}
|
||||
20
part_3/3.10/1.go
Normal file
20
part_3/3.10/1.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func createGenerator(start int, end int) chan int {
|
||||
ch := make(chan int, end-start)
|
||||
go func(ch chan int) {
|
||||
for i := start; i <= end; i++ {
|
||||
ch <- i // помещение значения в канал
|
||||
}
|
||||
close(ch)
|
||||
}(ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
func main() {
|
||||
for it := range createGenerator(1, 10) {
|
||||
fmt.Printf("%d || ", it)
|
||||
}
|
||||
}
|
||||
25
part_3/3.10/2.go
Normal file
25
part_3/3.10/2.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func createGenerator(start int, end int) chan int {
|
||||
ch := make(chan int, end-start)
|
||||
go func(ch chan int) {
|
||||
for i := start; i <= end; i++ {
|
||||
ch <- i // помещение значения в канал
|
||||
}
|
||||
close(ch)
|
||||
}(ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
func main() {
|
||||
generator := createGenerator(4, 8)
|
||||
for {
|
||||
value := <-generator // распаковка значения из канала в переменную
|
||||
fmt.Printf("%d || ", value)
|
||||
if len(generator) <= 0 { // проверка на выход из бесконечного цикла
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
12
part_3/3.11/1.go
Normal file
12
part_3/3.11/1.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
for i := 0; i < 3; i++ {
|
||||
defer fmt.Printf("%d ", i)
|
||||
}
|
||||
}
|
||||
|
||||
// Finish!
|
||||
// 2 1 0
|
||||
13
part_3/3.11/2.go
Normal file
13
part_3/3.11/2.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
defer fmt.Printf("%d ", 0)
|
||||
defer fmt.Printf("%d ", 1)
|
||||
defer fmt.Printf("%d ", 2)
|
||||
fmt.Println("Finish!")
|
||||
}
|
||||
|
||||
// Finish!
|
||||
// 2 1 0
|
||||
19
part_3/3.2/1.go
Normal file
19
part_3/3.2/1.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
array := [4]float64{2.4, 5.6, 8.1, 9.22}
|
||||
myFunc(array)
|
||||
fmt.Printf("Array in main: %v\n", array)
|
||||
}
|
||||
|
||||
func myFunc(array [4]float64) {
|
||||
for i := range array {
|
||||
array[i] += 2.33
|
||||
}
|
||||
fmt.Printf("Array in myFunc: %v\n", array)
|
||||
}
|
||||
|
||||
// Array in myFunc: [4.73 7.93 10.43 11.55]
|
||||
// Array in main: [2.4 5.6 8.1 9.22]
|
||||
19
part_3/3.2/2.go
Normal file
19
part_3/3.2/2.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
array := [4]float64{2.4, 5.6, 8.1, 9.22}
|
||||
myFunc(&array)
|
||||
fmt.Printf("Array in main: %v\n", array)
|
||||
}
|
||||
|
||||
func myFunc(array *[4]float64) {
|
||||
for i := range array {
|
||||
array[i] += 2.33
|
||||
}
|
||||
fmt.Printf("Array in myFunc: %v\n", *array)
|
||||
}
|
||||
|
||||
// Array in myFunc: [4.73 7.93 10.43 11.55]
|
||||
// Array in main: [4.73 7.93 10.43 11.55]
|
||||
19
part_3/3.2/3.go
Normal file
19
part_3/3.2/3.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
array := []float64{2.4, 5.6, 8.1, 9.22}
|
||||
myFunc(&array)
|
||||
fmt.Printf("Array in main: %v\n", array)
|
||||
}
|
||||
|
||||
func myFunc(array *[]float64) {
|
||||
for i := range *array {
|
||||
(*array)[i] += 1.5
|
||||
}
|
||||
fmt.Printf("Array in myFunc: %v\n", *array)
|
||||
}
|
||||
|
||||
// Array in myFunc: [3.9 7.1 9.6 10.72]
|
||||
// Array in main: [3.9 7.1 9.6 10.72]
|
||||
15
part_3/3.2/4.go
Normal file
15
part_3/3.2/4.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
a, b, rez := 10, 13, 0
|
||||
add(a, b, &rez)
|
||||
fmt.Printf("%d + %d = %d\n", a, b, rez)
|
||||
}
|
||||
|
||||
func add(a, b int, rez *int) {
|
||||
*rez = a + b
|
||||
}
|
||||
|
||||
// 10 + 13 = 23
|
||||
35
part_3/3.2/5.go
Normal file
35
part_3/3.2/5.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func find1(slice *[]int, value int, check *bool) {
|
||||
*check = false
|
||||
for i := range *slice {
|
||||
if (*slice)[i] == value {
|
||||
*check = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func find2(slice *[]int, value int) bool {
|
||||
for i := range *slice {
|
||||
if (*slice)[i] == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func main() {
|
||||
slice := []int{2, 4, 5, 7, 103, 55}
|
||||
var check bool
|
||||
value := 2
|
||||
find1(&slice, value, &check)
|
||||
fmt.Printf("%d contains in slice? %t\n", value, check)
|
||||
value = 22
|
||||
fmt.Printf("%d contains in slice? %t\n", value, find2(&slice, value))
|
||||
}
|
||||
|
||||
// 2 contains in slice? true
|
||||
// 22 contains in slice? false
|
||||
18
part_3/3.3/1.go
Normal file
18
part_3/3.3/1.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func myFunc(value map[string]map[string][]int) {
|
||||
fmt.Println(value)
|
||||
}
|
||||
|
||||
func main() {
|
||||
myMap := map[string]map[string][]int{
|
||||
"a": {"a2": []int{2, 5, 3}},
|
||||
"b": {"bbc": []int{0, 10, 3}},
|
||||
"c": {"alex": []int{}},
|
||||
}
|
||||
myFunc(myMap)
|
||||
}
|
||||
|
||||
// map[a:map[a2:[2 5 3]] b:map[bbc:[0 10 3]] c:map[alex:[]]]
|
||||
20
part_3/3.3/2.go
Normal file
20
part_3/3.3/2.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type MyType map[string]map[string][]int
|
||||
|
||||
func myFunc(value MyType) {
|
||||
fmt.Println(value)
|
||||
}
|
||||
|
||||
func main() {
|
||||
myMap := MyType{
|
||||
"a": {"a2": []int{2, 5, 3}},
|
||||
"b": {"bbc": []int{0, 10, 3}},
|
||||
"c": {"alex": []int{}},
|
||||
}
|
||||
myFunc(myMap)
|
||||
}
|
||||
|
||||
// map[a:map[a2:[2 5 3]] b:map[bbc:[0 10 3]] c:map[alex:[]]]
|
||||
19
part_3/3.4/1.go
Normal file
19
part_3/3.4/1.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var global string = "Global value"
|
||||
|
||||
// global := "Global value" // так объявлять нельзя, будет ошибка
|
||||
|
||||
func myFunc() {
|
||||
fmt.Println(global)
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(global)
|
||||
myFunc()
|
||||
}
|
||||
|
||||
// Global value
|
||||
// Global value
|
||||
18
part_3/3.4/2.go
Normal file
18
part_3/3.4/2.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var global string = "Global value"
|
||||
|
||||
func myFunc() {
|
||||
global := 10
|
||||
fmt.Println(global)
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(global)
|
||||
myFunc()
|
||||
}
|
||||
|
||||
// Global value
|
||||
// 10
|
||||
20
part_3/3.4/3.go
Normal file
20
part_3/3.4/3.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var global string = "Global value"
|
||||
|
||||
func myFunc() {
|
||||
global := 10
|
||||
fmt.Println(global)
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(global)
|
||||
myFunc()
|
||||
if true {
|
||||
local := 20
|
||||
fmt.Println(local)
|
||||
}
|
||||
local = 5 // undefined: local
|
||||
}
|
||||
23
part_3/3.4/4.go
Normal file
23
part_3/3.4/4.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var global string = "Global value"
|
||||
|
||||
func myFunc() {
|
||||
global := 10
|
||||
fmt.Println(global)
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(global) // Global value
|
||||
local := 20
|
||||
{
|
||||
fmt.Println(local) // 20
|
||||
{
|
||||
local := 10
|
||||
fmt.Println(local) // 10
|
||||
}
|
||||
fmt.Println(local) // 20
|
||||
}
|
||||
}
|
||||
13
part_3/3.5/1.go
Normal file
13
part_3/3.5/1.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func main() {
|
||||
myFunc := add // var myFunc func(a int, b int) int = add
|
||||
fmt.Println(add(3, 5)) // 8
|
||||
fmt.Println(myFunc(3, 5)) // 8
|
||||
}
|
||||
17
part_3/3.6/1.go
Normal file
17
part_3/3.6/1.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func sub(c, a, b int, addFunc func(a int, b int) int) int {
|
||||
return c - addFunc(a, b)
|
||||
}
|
||||
|
||||
func main() {
|
||||
myFunc := add // var myFunc func(a int, b int) int = add
|
||||
fmt.Println(sub(4, 3, 10, add)) // -9
|
||||
fmt.Println(sub(4, 3, 10, myFunc)) // -9
|
||||
}
|
||||
19
part_3/3.6/2.go
Normal file
19
part_3/3.6/2.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type MyFunctionAdd func(a int, b int) int
|
||||
|
||||
func add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func sub(c, a, b int, addFunc MyFunctionAdd) int {
|
||||
return c - addFunc(a, b)
|
||||
}
|
||||
|
||||
func main() {
|
||||
myFunc := add // var myFunc func(a int, b int) int = add
|
||||
fmt.Println(sub(4, 3, 10, add)) // -9
|
||||
fmt.Println(sub(4, 3, 10, myFunc)) // -9
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user