Skip to content

Latest commit

 

History

History
218 lines (171 loc) · 12.7 KB

File metadata and controls

218 lines (171 loc) · 12.7 KB

Go

Описание

Go (часто также Golang) — компилируемый многопоточный язык программирования, разработанный внутри компании Google

Язык Go разрабатывался как язык программирования для создания высокоэффективных программ, работающих на современных распределённых системах и многоядерных процессорах. Он может рассматриваться как попытка создать замену языкам C/C++. По словам Роба Пайка, "Go был разработан для решения реальных проблем, возникающих при разработке программного обеспечения в Google". В качестве основных таких проблем он называет:

  • Медленную сборку программ
  • Неконтролируемые зависимости
  • Использование разными программистами разных подмножеств языка
  • Затруднения с пониманием программ, вызванные неудобочитаемостью кода, плохим документированием
  • Дублирование разработок
  • Высокую стоимость обновлений
  • Несинхронные обновления при дублировании кода
  • Сложность разработки инструментария

Основными требованиями к языку стали:

  • Ортогональность. Язык должен предоставлять небольшое число средств, не повторяющих функциональность друг друга
  • Простая и регулярная грамматика. Минимум ключевых слов, простая, легко разбираемая грамматическая структура, легко читаемый код
  • Простая работа с типами. Типизация должна обеспечивать безопасность, но не превращаться в бюрократию, лишь увеличивающую код. Отказ от иерархии типов, но с сохранением объектно-ориентированных возможностей
  • Отсутствие неявных преобразований
  • Сборка мусора
  • Встроенные средства распараллеливания, простые и эффективные
  • Поддержка строк, ассоциативных массивов и коммуникационных каналов
  • Чёткое разделение интерфейса и реализации
  • Эффективная система пакетов с явным указанием зависимостей, обеспечивающая быструю сборку

Go создавался в расчёте на то, что программы на нём будут транслироваться в объектный код целевой аппаратной и программной платформы и в дальнейшем исполняться непосредственно, не требуя виртуальной машины, поэтому одним из критериев выбора архитектурных решений была возможность обеспечить быструю компиляцию в эффективный объектный код и отсутствие чрезмерных требований к динамической поддержке.

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

Основные возможности

  • Go — язык со строгой статической типизацией. Доступен автоматический вывод типов, для пользовательских типов — "утиная типизация"
  • Полноценная поддержка указателей, но без возможности применять к ним арифметические операции, в отличие от C/C++
  • Строковый тип со встроенной поддержкой Unicode
  • Использование динамических массивов, хеш-таблиц, срезов (слайсов), вариант цикла для обхода коллекции
  • Средства функционального программирования: неименованные функции, замыкания, передача функций в параметрах и возврат функциональных значений
  • Автоматическое управление памятью со сборщиком мусора
  • Средства объектно-ориентированного программирования, но без поддержки наследования реализации (наследуются только интерфейсы). По большому счёту, Go является процедурным языком с поддержкой интерфейсов
  • Средства параллельного программирования: встроенные в язык потоки (go routines), взаимодействие потоков через каналы и другие средства организации многопоточных программ
  • Достаточно лаконичный и простой синтаксис, основанный на Си, но существенно доработанный, с большим количеством синтаксического сахара

Типы данных

  • Целые числа
    • int, int8, int16, int32, int64 и rune (то же самое, что int32)
    • uint, uintptr, uint8, uint16, uint32, uint64 и byte (то же самое, что uint8)
  • Числа с плавающей точкой
    • float32 и float64
    • complex64 и complex128
  • Строки
    • string
  • Логические значения
    • bool

Установка

# Ubuntu
sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install golang-go
# macOS
brew install golang

Примеры кода

Hello World

package main

import "fmt"

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

Пакеты

package main
/* Импорт */
import (
	"fmt"           // Стандартный пакет для форматированного вывода
	"database/sql"  // Импорт вложенного пакета
	w "os"          // Импорт с псевдонимом
	. "math"        // Импорт без квалификации при использовании
	_ "gopkg.in/goracle.v2"  // Пакет не имеет явных обращений в коде
)

func main() {
    for _, arg := range w.Args {  // Обращение к массиву Args, объявленному в пакете "os", через псевдоним
        fmt.Println(arg)  // Обращение к функции Println(), объявленной в пакете "fmt", с именем пакета
    }
    db *sql.DB = sql.Open(driver, dataSource)  // Имена из вложенного пакета квалифицируются только именем самого пакета (sql)
    x := Sin(1.0) // вызов math.Sin() - квалификация именем пакета math не нужна,
                  // так как он импортирован без имени
    // Обращений к пакету "goracle.v2" в коде нет, но он будет импортирован. 
}

Механизм отложенного вызова

// Функция, копирующая файл
func CopyFile(dstName, srcName string) (written int64, err error) { 
    src, err := os.Open(srcName)  // Открытие файла-источника
    if err != nil {               // Проверка
        return                    // Если неудача, возврат с ошибкой
    }
    // Если пришли сюда, то файл-источник был успешно открыт 
    defer src.Close()  // Отложенный вызов: src.Close() будет вызван по завершении CopyFile

    dst, err := os.Create(dstName) // Открытие файла-приёмника
    if err != nil {                // Проверка и возврат при ошибке 
        return
    }
    defer dst.Close()  // Отложенный вызов: dst.Close() будет вызван по завершении CopyFile

    return io.Copy(dst, src)  // Копирование данных и возврат из функции
    // После всех операций будут вызваны: сначала dst.Close(), затем src.Close()
}

Обработка ошибок

func ReadFile(srcName string)(result string, err error) {
    file, err := os.Open("file.txt")
    if err != nil {
        // Генерация новой ошибки с уточняющим текстом
        return nil, fmt.Errorf("Ошибка при чтении файла %s: %g\n", srcName, err) 
    } 
    ... // Дальнейшее исполнение функции, если ошибки не было
    return result, nil  // Возврат результата и пустой ошибки, если выполнение успешно
}

Goroutines

func main() {
	var wg sync.WaitGroup  // Создание waitgroup. Исходное значение счётчика - 0
	logger := log.New(os.Stdout, "", 0)  // log.Logger - потоково-безопасный тип для вывода
	for _, arg := range os.Args {  // Цикл по всем аргументам командной строки
		wg.Add(1)  // Увеличение счётчика waitgroup на единицу
		// Запуск go-процедуры для обработки параметра arg
		go func(word string) {
			// Отложенное уменьшение счётчика waitgroup на единицу.
			// Произойдёт по завершении функции.
			defer wg.Done()
			logger.Println(prepareWord(word))  // Выполнение обработки и вывод результата
		}(arg)
	}
	wg.Wait()  // Ожидание, пока счётчик в waitgroup wg не станет равным нулю.
}

Каналы

in := make(chan string, 0) // Создание небуферизованного канала in
out := make(chan int, 10)  // Создание буферизованного канала out
...
in <- arg  // запись значения в канал in
...
r1 := <- out  // чтение из канала out 
...
r2, ok := <- out  // чтение с проверкой закрытия канала
if ok {  // если ok == true - канал открыт
   ...
} else {  // если канал закрыт, делаем что-то ещё
   ...
}

Интроспекция — показать все методы объекта

fooType := reflect.TypeOf(someObj)
for i := 0; i < fooType.NumMethod(); i++ {
	method := fooType.Method(i)
	fmt.Println(method.Name)
}

Полезные ссылки