Решил потратить выходные с пользой, и вернутся к изучению Go. У меня было примерно 20 часов, за которые я успел изучить все что мне нужно и написал довольно простой mvc-like фреймворк. Начем по порядоку.
До этого момента я пробовал Go около 3х лет назад, непомню какая была версия, но помню о Go тогда только начали узнавать. О самом языке тогда небыло ничего ясно кроме того что он от Google. И что многие известные люди успешно разрабатывают на Go например Brad Fitzpatrik
Непросто так упоминаю Бреда Фитцпатрика, а потому что первое приложение на Go в исходники которого я смотрел был Camilstore - персональное хранилище с синхронзацией. На тот момент это казалось непостижимо сложными и трудно изучаемым, прошло время и про Go стали говорить больше и не только в “долине”.
До этого я много писал на ruby и javascript, и php и python, потому для меня интересно как Go будет решать те задачи которые уже можно было решать с помошью известных мне инструментов и как создавать на нем то для чего сам язык и предназначался.
Вопросы которые для меня важны когда я изучаю новый ЯП
- Документация
- Наличие готовых библиотек и рабочих проудктов
- Наличие комьюнити
- Наличие качественной библиотеки для работы с БД
- Быстрое понимание
- Приятный синтаксис
Примерно через 20 часов я получил положительные ответы на свои вопросы
Что такое язык Go ?
Это компилируемый язык со статической типизацией, предназначенный для реализации высокопроизводительных паралельных вычислений, в нем есть garbage collector, memory safety - безопасный доступ к памяти, а также CSP который как раз используется для описания паралельных вычислейний. Go похож на C но с улучшениями в сторону понимания, простоты и безопасности.
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
Вконце будут ссылки по которым можно понятно и подробно прочитать про Go.
А ниже немного интересных моментов языка.
Неопределенное количество аргументов
func Nice(first string, shits ...string) int64 {
}
Struct / Структуры
Структура это набор поименовынх элементов определенного типа. Структуры можно наследовать, а точнее включать одну или несколько в другую.
// A struct with 6 fields.
struct {
x, y int
u float32
_ float32
A *[]int
F func()
}
Пример встаривания структур
type Animal struct {
Name string
}
type Cat struct {
Animal
Breed string
}
Структура также может быть определена с использованием тега Подбронее
struct {
camelCaseString uint64 `json:"came_case_string"`
serverIP6 uint64 `json:"server_ip6"`
}
Тег используется во вспомогательных целях, в данном примере он указывает на то что в случае представляени структуры в виде json, названия полей в структуре будет заменены на указанные в теге. Это очень удобная нотация, ее используют многие другие пакеты на Go.
Interfaces / Интерфейсы
type Shape interface {
area() float64
}
Channels / Каналы
Канал предоставляет механизм конкуретного вызова функций. С помощью его можно оргазовывать пайплайны (pipelines)
chan T // can be used to send and receive values of type T
chan<- float64 // can only be used to send float64s
<-chan int // can only be used to receive ints
Пример работы каналов (взял отсюда)
package main
import "fmt"
import "time"
func doIt(done chan bool) {
fmt.Print("working...")
time.Sleep(time.Second)
fmt.Println("done")
// send value to channel
done <- true
}
func main() {
// We're creating channel and
// starting doIt function as gorouine
done := make(chan bool)
go doIt(done)
// reading from channel with `<-` blocks program until
// we receive value after one second in `doIt` function
a := <-done
fmt.Println(a)
}
Это очень простой пример каналов, больше примеров ищите по ссылкам в конце поста.
Goroutines
Отложенные процедуры Пример
Отложенны процедуры или функции выполняются асинхронно независимо от других частей программы.
// A _goroutine_ is a lightweight thread of execution.
package main
import "fmt"
func f(from string) {
for i := 0; i < 3; i++ {
fmt.Println(from, ":", i)
}
}
func main() {
// Suppose we have a function call `f(s)`. Here's how
// we'd call that in the usual way, running it
// synchronously.
f("direct")
// To invoke this function in a goroutine, use
// `go f(s)`. This new goroutine will execute
// concurrently with the calling one.
go f("goroutine")
// You can also start a goroutine for an anonymous
// function call.
go func(msg string) {
fmt.Println(msg)
}("going")
// Our two function calls are running asynchronously in
// separate goroutines now, so execution falls through
// to here. This `Scanln` code requires we press a key
// before the program exits.
var input string
fmt.Scanln(&input)
fmt.Println("done")
}
Кроме goroutines в Go есть инструкция defer с помощью которой можно выполнять функции в конце заверешния работы текущего scope функции. Пример работы defer
Тесты
Для тестирования в Go существует стандартная библиотека testing
Простой пример с использованием стороннего пакета для assertion
Нужно обратит внимание что тесты в Go должны находится в файлах с суффиксом test soulkitchen_test.go а методы внутри дожныы иметь префикс Test
package soulkitchen
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestNew(t *testing.T) {
assert := assert.New(t)
assert.Nil(nil)
}
Нестал писать скольконибудь подробное тестирование, но простейший пример привел. Запуск тестов в данном случае это выполнение в корне проекта команды:
go test
которая запустит все тесты в текущей директрии
go test
PASS
ok github.com/noroot/soulkitchen 0.014s
Кроме тестов в Go существуют бенчмарки (Benchmarks) которые позволяют понять насколько быстро работают написанные механизмы. Чтобы воспользоваться бенчмарками нужно сделать особо обьявленный метод.
func BenchmarkHello(b *testing.B) {
for i := 0; i < b.N; i++ {
fmt.Sprintf("hello")
}
}
Бенчмарки запускаются с помощью команды
go test -bench .
В качестве параметра к ключу bench указывается регулярное выражение маска для того чтобы определить какие бенчмарки запускать Подробнее про возможные параметры запуска здесь
Coding style
Для соблюдения конвенций по стилю форматирования файлов, в Go предусмотрена специальная утилита gofmt которая форматирует исходный код.
gofmt src/main.go
В Go для отступов принята табулция шириной 8.
Документация
Утилита godoc которая идет в комплекте в месте языком умеет делать очень полезнюу вешь, а именно серфить докумнетацию, причем локально. Для это нужно запустить команду и открыть браузер
godoc -http=:6060
Пример
Пример программы на Go в котором GET запросом получается контент страницы. Примре избыточен в нем показано сразу несколько фич Go (каналы, интерфейсы, замыкания, отложенные процедуры)
package main
import (
"io/ioutil"
"log"
"net/http"
)
func Future(f func() (interface{}, error)) func() (interface{}, error) {
var result interface{}
var err error
c := make(chan struct{}, 1)
go func() {
defer close(c)
result, err = f()
}()
return func() (interface{}, error) {
<-c
return result, err
}
}
func main() {
url := "http://labs.strava.com"
future := Future(func() (interface{}, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
})
// do many other things
b, err := future()
body, _ := b.([]byte)
log.Printf("response length: %d", len(body))
log.Printf("request error: %v", err)
}
Подсмотрел здесь
Впечателния
Ощущения такие что нашел язык на котором надо программировать, а не просто собирать что-то из кубиков. Oldschool ощущения подобные те которые можно испытывать программируя на C при этом код не сильно сложнее чем Nodejs.
Про производительсноть, - она очень высокая, особенно в сравнении ruby, php и python, но хочется предостеречь от всяког рода холиваров потомучто в итоге нужны нормальные полноценные бенчмарки, а их как всегда нужно делать или как минимум проверять самому.
Вначале заметки я писал что взялся за реализацию MVC, да это довольно просто, но начинает почти сразуже обрастать типовыми задачами, поэтому имеет смысл взять готовый web-фреймворк которых на Go полно, а особенно много мини-фреймворков котоырй реализуют routing и handlers аналогично expressjs.
Напоследок вставлю список проектов написанных на Go в нем довольно много интересного например Docker. А это как минмум значит что Docker это next big thing к которой стоит пресмотреться.
Это просто заметка, а не мануал, читайте документацию, во Go она отличная.
Ссылки
Курируемый список библиотек и инструментов на Go
Много примеров типовых решений на Go
Comments powered by Talkyard.