Готовые программы на Golang
Go (или Golang) — это язык программирования, разработанный компанией Google, который сочетает в себе производительность компилируемых языков и удобство динамических языков. Он широко используется для создания высокопроизводительных серверных приложений, микросервисов, а также в области облачных технологий и обработки данных.
В этой статье рассмотрим несколько примеров программ на Go, чтобы показать основные принципы работы с этим языком, его особенности и преимущества. Представляем готовые программы на Golang, которые вы можете скопировать себе и поизучать.
👣 Golang Go – авторский канал, посвященный Go разработке, Devops и созданию высоконагруженных сервисов.
1. Простая программа: “Hello, World!”
Как и в любом языке программирования, начнём с самой простой программы, которая выводит строку на экран:
goКопировать кодpackage main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Пояснение:
package main
— указывает, что это основной пакет программы.import "fmt"
— импортирует пакетfmt
, который предоставляет функции для форматированного ввода/вывода.func main()
— основная функция, с которой начинается выполнение программы.fmt.Println()
— выводит строку на экран.
2. Ввод и вывод данных
Давайте напишем программу, которая запрашивает у пользователя его имя и выводит приветствие:
goКопировать кодpackage main
import (
"fmt"
)
func main() {
var name string
fmt.Print("Введите ваше имя: ")
fmt.Scanln(&name)
fmt.Printf("Привет, %s!\n", name)
}
Пояснение:
var name string
— объявление переменнойname
типаstring
.fmt.Print()
— выводит текст без перевода строки.fmt.Scanln(&name)
— считывает строку с клавиатуры и сохраняет её в переменнуюname
.fmt.Printf()
— выводит форматированную строку, подставляя значение переменной в место%s
.
3. Простой калькулятор
Теперь создадим программу, которая выполняет сложение двух чисел, введённых пользователем:
goКопировать кодpackage main
import (
"fmt"
)
func main() {
var num1, num2 float64
fmt.Print("Введите первое число: ")
fmt.Scanln(&num1)
fmt.Print("Введите второе число: ")
fmt.Scanln(&num2)
sum := num1 + num2
fmt.Printf("Сумма чисел: %.2f\n", sum)
}
Пояснение:
var num1, num2 float64
— объявление двух переменных типаfloat64
для хранения чисел с плавающей запятой.- Ввод данных осуществляется через
fmt.Scanln(&num1)
иfmt.Scanln(&num2)
. - Результат вычисления выводится с помощью
fmt.Printf()
с форматом, ограничивающим вывод до двух знаков после запятой (%.2f
).
4. Нахождение факториала числа
Пример программы, которая вычисляет факториал числа с помощью рекурсии:
goКопировать кодpackage main
import (
"fmt"
)
func factorial(n int) int {
if n == 0 {
return 1
}
return n * factorial(n-1)
}
func main() {
var num int
fmt.Print("Введите число для нахождения факториала: ")
fmt.Scanln(&num)
fmt.Printf("Факториал числа %d равен %d\n", num, factorial(num))
}
Пояснение:
- Функция
factorial(n int)
вычисляет факториал числа с помощью рекурсии. Когдаn == 0
, возвращается 1, иначе возвращаетсяn * factorial(n-1)
. - Ввод числа осуществляется через
fmt.Scanln(&num)
, после чего результат выводится черезfmt.Printf()
.
5. Работа с массивами
В Go массивы имеют фиксированный размер. Рассмотрим пример программы, которая находит сумму элементов массива:
goКопировать кодpackage main
import "fmt"
func main() {
var numbers = [5]int{1, 2, 3, 4, 5}
var sum int
for _, number := range numbers {
sum += number
}
fmt.Printf("Сумма элементов массива: %d\n", sum)
}
Пояснение:
var numbers = [5]int{1, 2, 3, 4, 5}
— создание массива из 5 элементов.for _, number := range numbers
— цикл, который итерирует по всем элементам массива._
используется для игнорирования индекса элемента (мы его не используем).number
— значение текущего элемента массива.
- Суммирование элементов массива происходит в теле цикла, результат выводится через
fmt.Printf()
.
6. Использование слайсов
Слайсы — это динамические массивы в Go. Они могут изменять свой размер во время выполнения программы. Рассмотрим пример программы, которая добавляет элементы в слайс:
goКопировать кодpackage main
import "fmt"
func main() {
var numbers []int
numbers = append(numbers, 1, 2, 3, 4, 5)
fmt.Println("Содержимое слайса:", numbers)
}
Пояснение:
var numbers []int
— объявление слайса целых чисел.append(numbers, 1, 2, 3, 4, 5)
— добавление элементов в слайс.fmt.Println()
выводит содержимое слайса на экран.
7. Создание простого HTTP-сервера
Go идеально подходит для создания высокопроизводительных веб-сервисов. Рассмотрим пример создания простого HTTP-сервера, который будет отдавать страницу “Hello, World!”:
goКопировать кодpackage main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", handler)
fmt.Println("Запуск сервера на порту 8080...")
http.ListenAndServe(":8080", nil)
}
Пояснение:
http.HandleFunc("/", handler)
— регистрирует обработчик запросов, который будет вызываться при обращении к корневому URL (/
).fmt.Fprintln(w, "Hello, World!")
— отправляет ответ с текстом “Hello, World!” клиенту.http.ListenAndServe(":8080", nil)
— запускает HTTP-сервер на порту 8080.
Запустив эту программу, можно обратиться к серверу по адресу http://localhost:8080
и увидеть ответ “Hello, World!”.
8. Горутины и каналы
Одна из ключевых особенностей Go — это поддержка конкурентности с помощью горутин и каналов. Рассмотрим пример, где несколько горутин одновременно выполняют задачи:
goКопировать кодpackage main
import (
"fmt"
"time"
)
func sayHello() {
time.Sleep(2 * time.Second)
fmt.Println("Привет из горутины!")
}
func main() {
go sayHello() // Запускаем горутину
fmt.Println("Основная программа продолжает работать...")
time.Sleep(3 * time.Second) // Ждем, чтобы горутина успела завершиться
}
Пояснение:
go sayHello()
— запускает функциюsayHello
в новой горутине.time.Sleep(2 * time.Second)
— имитирует задержку в горутине.main()
также выполняется, не ожидая завершения горутины, но мы добавляем задержку, чтобы горутина успела выполнить свою работу.
Горутины выполняются параллельно, и таким образом программа не блокирует выполнение основного потока при запуске дополнительных горутин.
Давайте создадим более сложную программу на Go, которая будет выполнять задачу управления задачами (Task Manager). В этом примере мы будем использовать базу данных SQLite для хранения данных о задачах, а также реализуем API с использованием фреймворка Gin для создания веб-приложения. Программа будет поддерживать следующие действия:
- Добавление новой задачи.
- Просмотр всех задач.
- Обновление задачи.
- Удаление задачи.
Мы будем использовать Gin для построения REST API и SQLite для хранения данных о задачах.
Шаги:
- Установим зависимости.
- Создадим структуру проекта.
- Реализуем работу с базой данных SQLite.
- Напишем код для обработки HTTP-запросов.
- Реализуем взаимодействие с API.
1. Установка зависимостей
Для начала установим нужные зависимости:
- Gin — для создания REST API.
- SQLite — для работы с базой данных.
bashКопировать кодgo get -u github.com/gin-gonic/gin
go get -u github.com/mattn/go-sqlite3
2. Структура проекта
Предположим, структура проекта будет такой:
bashКопировать кодtask-manager/
│
├── main.go # Основной файл программы
├── database.go # Работа с базой данных
└── models.go # Структуры данных
3. Реализация работы с базой данных (database.go
)
Этот файл будет отвечать за подключение к базе данных SQLite и выполнение SQL-запросов.
goКопировать кодpackage main
import (
"database/sql"
"log"
_ "github.com/mattn/go-sqlite3"
)
var db *sql.DB
// Инициализация базы данных
func initDB() {
var err error
db, err = sql.Open("sqlite3", "./tasks.db")
if err != nil {
log.Fatal(err)
}
// Создание таблицы, если она еще не существует
query := `CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
description TEXT,
done BOOLEAN NOT NULL CHECK (done IN (0, 1))
);`
_, err = db.Exec(query)
if err != nil {
log.Fatal(err)
}
}
// Функция для добавления новой задачи в базу данных
func addTask(title, description string) (int64, error) {
query := `INSERT INTO tasks (title, description, done) VALUES (?, ?, ?)`
result, err := db.Exec(query, title, description, false)
if err != nil {
return 0, err
}
id, err := result.LastInsertId()
if err != nil {
return 0, err
}
return id, nil
}
// Функция для получения всех задач
func getTasks() ([]Task, error) {
rows, err := db.Query("SELECT id, title, description, done FROM tasks")
if err != nil {
return nil, err
}
defer rows.Close()
var tasks []Task
for rows.Next() {
var task Task
if err := rows.Scan(&task.ID, &task.Title, &task.Description, &task.Done); err != nil {
return nil, err
}
tasks = append(tasks, task)
}
return tasks, nil
}
// Функция для получения одной задачи по ID
func getTaskByID(id int) (Task, error) {
var task Task
query := "SELECT id, title, description, done FROM tasks WHERE id = ?"
row := db.QueryRow(query, id)
err := row.Scan(&task.ID, &task.Title, &task.Description, &task.Done)
if err != nil {
return Task{}, err
}
return task, nil
}
// Функция для обновления задачи
func updateTask(id int, title, description string, done bool) error {
query := `UPDATE tasks SET title = ?, description = ?, done = ? WHERE id = ?`
_, err := db.Exec(query, title, description, done, id)
return err
}
// Функция для удаления задачи
func deleteTask(id int) error {
query := `DELETE FROM tasks WHERE id = ?`
_, err := db.Exec(query, id)
return err
}
4. Модели данных (models.go
)
В этом файле будет храниться структура для задачи.
goКопировать кодpackage main
// Структура для задачи
type Task struct {
ID int `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Done bool `json:"done"`
}
5. Основной файл программы (main.go
)
В этом файле будет реализован HTTP-сервер с использованием Gin, который будет обрабатывать запросы API.
goКопировать кодpackage main
import (
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)
func main() {
// Инициализация базы данных
initDB()
defer db.Close()
// Создаем новый роутер Gin
r := gin.Default()
// Роуты API
r.GET("/tasks", getAllTasks)
r.GET("/tasks/:id", getTaskByID)
r.POST("/tasks", createTask)
r.PUT("/tasks/:id", updateTask)
r.DELETE("/tasks/:id", deleteTask)
// Запуск сервера
r.Run(":8080")
}
// Получение всех задач
func getAllTasks(c *gin.Context) {
tasks, err := getTasks()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, tasks)
}
// Получение задачи по ID
func getTaskByID(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
return
}
task, err := getTaskByID(id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Task not found"})
return
}
c.JSON(http.StatusOK, task)
}
// Создание новой задачи
func createTask(c *gin.Context) {
var newTask Task
if err := c.ShouldBindJSON(&newTask); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Добавляем задачу в базу данных
id, err := addTask(newTask.Title, newTask.Description)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
newTask.ID = int(id)
c.JSON(http.StatusCreated, newTask)
}
// Обновление существующей задачи
func updateTask(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
return
}
var updatedTask Task
if err := c.ShouldBindJSON(&updatedTask); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err = updateTask(id, updatedTask.Title, updatedTask.Description, updatedTask.Done)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Task not found"})
return
}
updatedTask.ID = id
c.JSON(http.StatusOK, updatedTask)
}
// Удаление задачи
func deleteTask(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
return
}
err = deleteTask(id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Task not found"})
return
}
c.JSON(http.StatusNoContent, gin.H{})
}
6. Запуск программы
После того как мы создали программу, можем её запустить. Выполните команду:
bashКопировать кодgo run main.go
Теперь сервер будет работать на порту 8080. Вы можете использовать Postman или любой другой HTTP-клиент, чтобы взаимодействовать с API:
Примеры запросов:
- GET /tasks — Получить все задачи.
- GET /tasks/{id} — Получить задачу по ID.
- POST /tasks — Создать новую задачу.
- Тело запроса:
{ "title": "Task 1", "description": "Description of Task 1" }
- Тело запроса:
- PUT /tasks/{id} — Обновить задачу.
- Тело запроса:
{ "title": "Updated Task", "description": "Updated description", "done": true }
- Тело запроса:
- DELETE /tasks/{id} — Удалить задачу.
Мы создали веб-приложение с API для управления задачами с использованием Go и Gin. В этом примере мы использовали SQLite для хранения данных, реализовали RESTful API для взаимодействия с данными и добавили основные CRUD-операции для задач.
Это приложение можно расширять, добавляя аутентификацию, более сложную логику обработки данных или фронтенд для работы с пользователем через веб-интерфейс.
Заключение
Go — это язык, который сочетает в себе простоту, высокую производительность и удобство работы с многозадачностью. Он идеально подходит для создания высоконагруженных систем, веб-сервисов, микросервисной архитектуры и многого другого.
В этой статье мы рассмотрели несколько примеров программ на Go, начиная с простых вводных программ и заканчивая созданием HTTP-сервера и использованием горутин. Благодаря своей простоте и возможностям Go стал популярным инструментом для разработки масштабируемых и производительных приложений.