Краткая справка по языку Go

Мне потребовалось сделать исполняемую программу и среди прочих попыток, самым простым вариантом оказалось использовать Go. Для знакомства с языком я собрал краткую справку (шпаргалку) и пользовался ей при написании кода.

Go (или Golang) — это язык программирования с открытым исходным кодом, разработанный в 2007 году в Google и представленный в 2009 году. Он ориентирован на простоту, производительность и поддерживаемость. Вот краткая справка по основным аспектам Go:

1. Основные особенности:

  • Компилируемый: Go — компилируемый язык, что обеспечивает высокую производительность программ.
  • Простота: Минималистичный синтаксис и набор инструментов делают Go легко обучаемым.
  • Сборка мусора (Garbage Collection): Go автоматизирует управление памятью.
  • Параллелизм: Встроенная поддержка горутин и каналов для упрощения параллельного и конкурентного программирования.

2. Синтаксис:

  • Переменные: Переменные объявляются с помощью ключевого слова var или оператора короткого присваивания :=. go var x int = 10 y := 20

  • Функции: go func add(a int, b int) int { return a + b }

  • Циклы: В Go только одна конструкция цикла — for. go for i := 0; i < 10; i++ { fmt.Println(i) }

  • Условия: go if x > 10 { fmt.Println("x is greater than 10") } else { fmt.Println("x is less than or equal to 10") }

3. Структуры:

Go не поддерживает классы, вместо этого используются структуры (struct).

type Person struct {
    Name string
    Age  int
}

p := Person{Name: "Alice", Age: 25}
fmt.Println(p.Name)

4. Интерфейсы:

Интерфейсы в Go определяют набор методов, который должен реализовать тип.

type Animal interface {
    Speak() string
}

type Dog struct {}

func (d Dog) Speak() string {
    return "Woof!"
}

5. Горутины и каналы:

  • Горутины: Легковесные потоки, запускаемые с помощью ключевого слова go. go go func() { fmt.Println("Hello from goroutine") }()

  • Каналы: Средство обмена данными между горутинами. go ch := make(chan int) go func() { ch <- 42 }() fmt.Println(<-ch)

6. Пакеты:

Каждый файл Go начинается с объявления пакета.

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

7. Преимущества:

  • Высокая производительность благодаря компиляции в машинный код.
  • Легкость в изучении и использовании.
  • Отличная поддержка конкурентности.
  • Статически типизированный язык, что уменьшает количество ошибок времени исполнения.

8. Недостатки:

  • Ограниченная поддержка ООП.
  • Отсутствие дженериков (но добавлены в Go 1.18).
  • Простейший набор стандартных библиотек для разработки более сложных решений.

Go отлично подходит для разработки высоконагруженных систем, веб-серверов, микросервисов, а также сетевых и облачных приложений.

package main

import (
    "bytes"
    "fmt"
    "io"
    "mime/multipart"
    "net/http"
    "os"
    "path/filepath"

    "gopkg.in/ini.v1"
)

// Чтение конфигурации из файла
func loadConfig(filename string) (string, string, string, error) {
    cfg, err := ini.Load(filename)
    if err != nil {
        return "", "", "", err
    }

    url := cfg.Section("").Key("url").String()
    filePath := cfg.Section("").Key("file").String()
    token := cfg.Section("").Key("accessToken").String()

    return url, filePath, token, nil
}

// Создание multipart-запроса с файлом
func createMultipartRequest(url string, filePath string, token string) (*http.Request, error) {
    // Открываем файл
    file, err := os.Open(filePath)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    // Создаем тело запроса
    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)

    part, err := writer.CreateFormFile("upload_file", filepath.Base(filePath))
    if err != nil {
        return nil, err
    }

    _, err = io.Copy(part, file)
    if err != nil {
        return nil, err
    }

    writer.Close()

    // Создаем запрос
    req, err := http.NewRequest("POST", url, body)
    if err != nil {
        return nil, err
    }

    // Добавляем заголовки
    req.Header.Add("Content-Type", writer.FormDataContentType())
    req.Header.Add("AccessToken", token)

    return req, nil
}

// Отправка запроса и обработка ответа
func sendRequest(req *http.Request) error {
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        return err
    }

    fmt.Println("Код ответа:", resp.StatusCode)
    fmt.Println("Ответ:", string(respBody))

    return nil
}

func main() {
    // Загрузка конфигурации
    url, filePath, token, err := loadConfig("config.ini")
    if err != nil {
        fmt.Println("Ошибка загрузки конфигурации:", err)
        return
    }

    // Создание запроса
    req, err := createMultipartRequest(url, filePath, token)
    if err != nil {
        fmt.Println("Ошибка создания запроса:", err)
        return
    }

    // Отправка запроса
    err = sendRequest(req)
    if err != nil {
        fmt.Println("Ошибка отправки запроса:", err)
    }
}