Note #24 Go и runtime
Существует много споров на тему
C одной стороны в Go есть рантайм, который написан на Go в отличии от Java(написан на С). C точки зрения архитектуры, рантайм - это просто коллекция нескольких уникальных частей, самые важные из которых: сборщик мусора и планировщик горутин (goroutine scheduler).
С другой стороны, Go рантайм также реализует фичи, которые экспортируются наружу c помощью пакета
Либо вывести сколько памяти занимает ваша программа:
Note: Также важно понимать, что Go рантайм не включает в себя виртуальную машину, а код программы на Go компилируется сразу в машинный код, кстати это позволяет нам так легко писать программы, которые легко портируются на разные ОС. Поэтому в контексте Go - когда говорят Go и runtime - это обычно имя пакета, а не виртуальное окружение в котором программа на Go запускается.
Существует много споров на тему
Go рантайм
и Go
пакета runtime
. Давайте разберемся с этим вопросом.C одной стороны в Go есть рантайм, который написан на Go в отличии от Java(написан на С). C точки зрения архитектуры, рантайм - это просто коллекция нескольких уникальных частей, самые важные из которых: сборщик мусора и планировщик горутин (goroutine scheduler).
С другой стороны, Go рантайм также реализует фичи, которые экспортируются наружу c помощью пакета
runtime
. C помощью пакета runtime
можно осуществлять управление сборщиком мусора и выводить различную дебаг информация см (runtime/debug).Либо вывести сколько памяти занимает ваша программа:
package main
import (
"runtime"
"fmt"
"time"
)
func PrintMememoryStats() {
var m runtime.MemStats
// The returned memory allocator statistics are up to date as of the call to ReadMemStats. This is in contrast with a heap profile, which is a snapshot as of the most recently completed garbage collection cycle.
runtime.ReadMemStats(&m)
fmt.Printf("Alloc = %v Mb", m.Alloc / 1024 / 1024)
fmt.Printf(" TotalAlloc = %v Mb", m.TotalAlloc / 1024 / 1024)
fmt.Printf(" Sys = %v Mb", m.Sys / 1024 / 1024)
fmt.Printf(" NumGC = %v\n", m.NumGC)
}
func main() {
PrintMememoryStats()
var total [][]int
for i := 0; i<3; i++ {
array := make([]int, 0, 4200000)
total = append(total, array)
PrintMememoryStats()
time.Sleep(time.Second)
}
PrintMememoryStats()
runtime.GC()
PrintMememoryStats()
}
Note: Также важно понимать, что Go рантайм не включает в себя виртуальную машину, а код программы на Go компилируется сразу в машинный код, кстати это позволяет нам так легко писать программы, которые легко портируются на разные ОС. Поэтому в контексте Go - когда говорят Go и runtime - это обычно имя пакета, а не виртуальное окружение в котором программа на Go запускается.
Note #25 Github Actions и Go
Решил посмотреть как обстоят дела у Github Actions и Go:
>Thanks for signing up for GitHub Actions!
>This account is already on the waitlist for the GitHub Actions Beta!
А пока я жду 🤣 Daniel Martí уже сделал отличный обзор[1] того, что уже работает 👍 и что не работает 👎 [2]
Полный пример конфигураций Github Actions и goreleaser и go1.13 можно найти в github репке проекта
Links:
[1] https://github.com/mvdan/github-actions-golang
[2] https://github.com/actions/setup-go/issues
[3] https://github.com/toshimaru/nyan/blob/master/.github/workflows/go.yml
P.S. кто знает как раздобыть инвайт напишите в личку @a_soldatenko
Решил посмотреть как обстоят дела у Github Actions и Go:
>Thanks for signing up for GitHub Actions!
>This account is already on the waitlist for the GitHub Actions Beta!
А пока я жду 🤣 Daniel Martí уже сделал отличный обзор[1] того, что уже работает 👍 и что не работает 👎 [2]
Полный пример конфигураций Github Actions и goreleaser и go1.13 можно найти в github репке проекта
nyan
aka colored cat [3]:Links:
[1] https://github.com/mvdan/github-actions-golang
[2] https://github.com/actions/setup-go/issues
[3] https://github.com/toshimaru/nyan/blob/master/.github/workflows/go.yml
P.S. кто знает как раздобыть инвайт напишите в личку @a_soldatenko
Note #26 LEAP year
Часто на собеседованиях в качестве разминки просят написать функцию, которая определяет является ли год высокосным или нет. Также подобную задачу можно найти в онлайн соревнованиях как SPOJ или CodeChef.
Т.е. сигнатура функции выглядит примерно так:
Самое близкое что я нашел было https://golang.org/pkg/time/#Time.YearDay:
> returns the day of the year specified by t, in the range [1,365] for non-leap years, and [1,366] in leap years.
После прочитанного пришла тривиальная идея, создать дату использую номер года и некоторые дефолтные параметры а именно последний день года, что позволит нам использовать метод
P.S. в качестве упражнения можно реализовать
P.P.S Отличный пример можно найти в доках
Links:
SPOJ - https://www.spoj.com/problems/ORTL1P07/
CodeChef - https://www.codechef.com/problems/LEAPY
алгоритм - https://en.wikipedia.org/wiki/Leap_year#Algorithm
Часто на собеседованиях в качестве разминки просят написать функцию, которая определяет является ли год высокосным или нет. Также подобную задачу можно найти в онлайн соревнованиях как SPOJ или CodeChef.
Т.е. сигнатура функции выглядит примерно так:
func IsLeapYear(y int) boolТак как использование стандартной библиотеки языка обычно не запрещено, то вдруг в голову пришла идея поискать, что там есть, после неудачного поиска по докам пакета
time
, как и ожидалось ничего подходящего не нашлось, я решил чуток подумать и сделать себе :coffee:Самое близкое что я нашел было https://golang.org/pkg/time/#Time.YearDay:
> returns the day of the year specified by t, in the range [1,365] for non-leap years, and [1,366] in leap years.
После прочитанного пришла тривиальная идея, создать дату использую номер года и некоторые дефолтные параметры а именно последний день года, что позволит нам использовать метод
YearDay
, чтобы проверить 31 декабря какой день 365-ый или 366-ой?func IsLeapYear(y int) bool {Далее естественно я полез смотреть исходники
year := time.Date(y, time.December, 31, 0, 0, 0, 0, time.Local)
days := year.YearDay()
if days > 365 {
return true
} else {
return false
}
}
time.YearDay
, и наткнулся на src/time/time.go:1329
func isLeap(year int) bool {Т.е полезная, но не экспортируемая функция isLeap :)
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
}
P.S. в качестве упражнения можно реализовать
func isLeap(year big.Int) bool
. P.P.S Отличный пример можно найти в доках
math/big
как вычислить фибоначчи используя арифметику больших чисел.Links:
SPOJ - https://www.spoj.com/problems/ORTL1P07/
CodeChef - https://www.codechef.com/problems/LEAPY
алгоритм - https://en.wikipedia.org/wiki/Leap_year#Algorithm
Note #27 Evolution of reverse string "Hello, 世界"
4 года назад мне попался интересный вопрос: как же развернуть строку используя Го?! Сложность заключается в том, чтобы не сломать UTF-8 символы которые могут быть в строке. Т.е. если решать в лоб то получим:
В 2009 Russ Cox в девелоперской рассылке golang-nuts [3] предложил решить эту задачку так:
Немного громоздко, но все же работает и сейчас (оставил оригинальное решение, понятное дело, что можно улучшить, Russ писал думаю пару минут):
>> fmt.Println(reverseString("世Hello, 世"))
>> 世 ,olleH世
Если не много упростить, используя тот факт, что строку можно конвертировать на прямую в
Идея та же, но код получился чуть более лаконичный.
Самое быстрое решение и не самое лаконичное:
И самый интересный на мой взгляд вариант с помощью
Это не самое быстрое решение, но оно показывает как используя замыкание мы сохраняем промежуточное значение в переменной
P.S. В качестве упражнения я рекомендую реализовать
"as⃝df̅" превратить в "f̅ds⃝a"
Links:
[1] https://github.com/golang/example/blob/master/stringutil/reverse.go
[2] https://golang.org/pkg/unicode/utf8/#DecodeRuneInString
[3] https://groups.google.com/forum/#!topic/golang-nuts/oPuBaYJ17t4
[4] http://rosettacode.org/wiki/Reverse_a_string
4 года назад мне попался интересный вопрос: как же развернуть строку используя Го?! Сложность заключается в том, чтобы не сломать UTF-8 символы которые могут быть в строке. Т.е. если решать в лоб то получим:
��� ,olleH���
, а хотелось бы 界世 ,olleH
.В 2009 Russ Cox в девелоперской рассылке golang-nuts [3] предложил решить эту задачку так:
func reverseString(s string) string {
n := 0
rune := make([]rune, len(s))
for _, r := range s {
rune[n] = r
n++
}
rune = rune[0:n]
// Reverse
for i := 0; i < n/2; i++ {
rune[i], rune[n-1-i] = rune[n-1-i], rune[i]
}
// Convert back to UTF-8.
return string(rune)
}
Немного громоздко, но все же работает и сейчас (оставил оригинальное решение, понятное дело, что можно улучшить, Russ писал думаю пару минут):
>> fmt.Println(reverseString("世Hello, 世"))
>> 世 ,olleH世
Если не много упростить, используя тот факт, что строку можно конвертировать на прямую в
[]rune
без дополнительного цикла [1]:func Reverse(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
Идея та же, но код получился чуть более лаконичный.
Самое быстрое решение и не самое лаконичное:
func ReverseFast(s string) string {
size := len(s)
buf := make([]byte, size)
for start := 0; start < size; {
r, n := utf8.DecodeRuneInString(s[start:])
start += n
utf8.EncodeRune(buf[size-start:], r)
}
return string(buf)
}
И самый интересный на мой взгляд вариант с помощью
defer
, рекомендую остановиться и подумать что же тут происходит на самом деле :func ReverseClosure(s string) (result string) {
for _, v := range s {
defer func(r rune) { result += string(r) }(v)
}
return
}
Это не самое быстрое решение, но оно показывает как используя замыкание мы сохраняем промежуточное значение в переменной
result
, для дальнейшего использования каждого defer вызова функции :)P.S. В качестве упражнения я рекомендую реализовать
func reverse(s string)
для так называемых “combining characters”. Те чтобы покрыть такой кейс:"as⃝df̅" превратить в "f̅ds⃝a"
Links:
[1] https://github.com/golang/example/blob/master/stringutil/reverse.go
[2] https://golang.org/pkg/unicode/utf8/#DecodeRuneInString
[3] https://groups.google.com/forum/#!topic/golang-nuts/oPuBaYJ17t4
[4] http://rosettacode.org/wiki/Reverse_a_string
Note # 28 fallthrough или “проваливаемся” дальше ⤵️
Go содержит интересное ключевое слово
Итак поехали 🚴♂️:
Т.е по дефолту в Go switch/case не проваливается дальше - это нужно делать явно используя ключевое слово
Не разрешается использовать в последнем операторе неважно это
Соответственно такой вариант вполне валидный:
Важный момент, "fallthrough" не разрешается использовать в связке с type switch:
Так же нельзя делать вложенные конструкции которые содержат
Useful links:
- ref - https://golang.org/ref/spec#Switch_statements
- wiki https://github.com/golang/go/wiki/Switch
Go содержит интересное ключевое слово
fallthrough
, которое на практике встречается довольно редко, его главная задача передать управление следующему оператору case
в условных конструкциях switch/case
. Итак поехали 🚴♂️:
func main() {
switch 42 {
case 42:
fmt.Println("First case: 42!")
fallthrough
default:
fmt.Println("Second case")
}
}
// First case: 42!
// Second case
Т.е по дефолту в Go switch/case не проваливается дальше - это нужно делать явно используя ключевое слово
fallthrough
.Не разрешается использовать в последнем операторе неважно это
case
или default
:func main() {
switch 42 {
case 42:
fmt.Println("First case: 42!")
default:
fmt.Println("Second case")
fallthrough
}
}
// cannot fallthrough final case in switch
Соответственно такой вариант вполне валидный:
func main() {
switch 42 {
default:
fmt.Println("Second case")
fallthrough
case 42:
fmt.Println("First case: 42!")
}
}
// First case: 42!
Важный момент, "fallthrough" не разрешается использовать в связке с type switch:
func main() {
var pi interface{} = 3.14
switch i := pi.(type) {
case int:
fmt.Printf("%v", i)
fallthrough
default:
fmt.Println("don't know the type")
}
}
// ./prog.go:18:3: cannot fallthrough in type switch
Так же нельзя делать вложенные конструкции которые содержат
fallthrough
☔️:func main() {
switch 42 {
case 42:
fmt.Println("First case: 42!")
if true {
fallthrough
}
case 1:
fmt.Println("First case: 1!")
}
}
// ./prog.go:18:4: fallthrough statement out of place
Useful links:
- ref - https://golang.org/ref/spec#Switch_statements
- wiki https://github.com/golang/go/wiki/Switch
Note #29 Testing.short или разделяем тестовые прогоны 📝
Недавно наткнулся на интересную тему: разделение Go тестов на быстрые или медленные те например unit и integration tests. Все собрал в короткую заметку:
A) Стандартный подход использую `testing.Short` [2]:
Если выполнить:
То мы пропустим тест
B) Использовать build tags самый, на мой взгляд, гибкий подход:
Те создаем
Далее просто запускаем:
С) Использовать -test.run RegExp [2]:
Можно именовать тесты с префиксом понятным всей команде:
И далее просто:
P.S. еще как вариант можно добавить разделение с помощью переменных окружения
А как сделано в вашем проекте? Поделиться можно в личку или чат
Links:
[1] https://golang.org/pkg/go/build/
[2] https://golang.org/cmd/go/#hdr-Testing_flags
[3] https://golang.org/pkg/testing/
Недавно наткнулся на интересную тему: разделение Go тестов на быстрые или медленные те например unit и integration tests. Все собрал в короткую заметку:
A) Стандартный подход использую `testing.Short` [2]:
func TestQuick(t *testing.T) {
...
}
func TestTimeConsuming(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
}
Если выполнить:
$ go test -short
То мы пропустим тест
TestTimeConsuming
и выполним только TestQuick
B) Использовать build tags самый, на мой взгляд, гибкий подход:
Те создаем
integration_test.go
файл и добавляем билд тэги [1]:// +build integration
func TestTimeConsuming(t *testing.T) {
// ...
}
Далее просто запускаем:
$ go test -tags=integration
С) Использовать -test.run RegExp [2]:
Можно именовать тесты с префиксом понятным всей команде:
func TestQuickUnit(t *testing.T) {
...
}
func TestIntegraion(t *testing.T) {
...
}
И далее просто:
$ go test -run Integration
$ go test -run Unit
P.S. еще как вариант можно добавить разделение с помощью переменных окружения
А как сделано в вашем проекте? Поделиться можно в личку или чат
Links:
[1] https://golang.org/pkg/go/build/
[2] https://golang.org/cmd/go/#hdr-Testing_flags
[3] https://golang.org/pkg/testing/
Note 30 # Go time podcast
Давно хотел порекомендовать подкаст, который слушаю постоянно: Go Time - очень интересный Go подкаст на англ языке - и вчера вышел юбилейный эпизод #100
в котором принимали участие Rob Pike и Robert Griesemer 🎉🎉🎉
Обсуждали историю Go, текущую работу и будущее 🚀
P.S. какие подкасты слушаете вы? Жаль что больше не выходят эпизоды https://golangshow.com/ :(
Enjoy: https://changelog.com/gotime/100
Давно хотел порекомендовать подкаст, который слушаю постоянно: Go Time - очень интересный Go подкаст на англ языке - и вчера вышел юбилейный эпизод #100
в котором принимали участие Rob Pike и Robert Griesemer 🎉🎉🎉
Обсуждали историю Go, текущую работу и будущее 🚀
P.S. какие подкасты слушаете вы? Жаль что больше не выходят эпизоды https://golangshow.com/ :(
Enjoy: https://changelog.com/gotime/100
Changelog
Creating the Go programming language featuring Rob Pike & Robert Griesemer (Go Time #100)
Carmen and Jon talk with Rob Pike and Robert Griesemer (the creators of Go) about its origins, growth, influence, and future. This an epic episode that dives deep into the history and details of the how's and why's of Go, and the choices they've made along…
Note #31 go run и exit code
Вчера в твиттере увидел как Джонни Бурсиквот задает вопрос[1]: почему
Крутой коммент от Дэйва Чейни (перевод):
“Go run - это для игрушечных программ, серьезные программы нужно компилировать и запускать” :lol:
Вот часть исходника go run [3] “We ignore exit status.”:
[1] Твиттер thread https://twitter.com/jboursiquot/status/1177296876779057152
[2] Issue 2015 года на эту тему: https://github.com/golang/go/issues/13440
[3] https://github.com/golang/go/blob/master/src/cmd/go/internal/run/run.go#L146-L148
Вчера в твиттере увидел как Джонни Бурсиквот задает вопрос[1]: почему
go run
всегда возвращает exit code 1:$ cat main.goА если собрать бинарник, а потом запустить то все будет ок:
package main
import "os"
func main() {
os.Exit(199)
}
$ go run main.go
exit status 199
$ echo $?
1
go build main.goСтранно почему он не догадался сразу, go run - это 2 процесса и соответственно 2 exit кода, однако go run может вернуть только один exit код :)
./main
$ echo $?
199
Крутой коммент от Дэйва Чейни (перевод):
“Go run - это для игрушечных программ, серьезные программы нужно компилировать и запускать” :lol:
Вот часть исходника go run [3] “We ignore exit status.”:
// buildRunProgram is the action for running a binary that has alreadyLinks:
// been compiled. We ignore exit status.
func buildRunProgram(b *work.Builder, a *work.Action) error {
…
}
[1] Твиттер thread https://twitter.com/jboursiquot/status/1177296876779057152
[2] Issue 2015 года на эту тему: https://github.com/golang/go/issues/13440
[3] https://github.com/golang/go/blob/master/src/cmd/go/internal/run/run.go#L146-L148
Twitter
Johnny Boursiquot
TIL: `go run` will always result in exit code 1, regardless of the exit code you use. For example, it may surprise you that this program does not exit with 199 when you `echo $?` in your shell if you use `go run` to exec it. `go build` does what you'd expect…
Note #32 negative slice/array indexes
Уже несколько раз попадается на глаза противоречивое предложение добавить в Go отрицательные индексы как в Python. Те сейчас негативные индексы вызывают панику:
А чтобы взять последний элемент slice’а, нужно написать так:
В Go 2 было предложено очередной раз добавить:
Идея не увенчалась успехом, хотя по-мнению автора это добавляет читаемость кода, что довольно спорно.
Но зато в комментариях я нашел другое предложение от Ian Lance Taylor:
> Использовать
Эту идею многие поддержали… но пока ни к чему не пришли.
P.S. Касательно
to be continued…
Links:
https://github.com/golang/go/issues/33359
https://github.com/golang/go/issues/16231
https://github.com/golang/go/issues/20176
https://github.com/golang/go/issues/11245
Уже несколько раз попадается на глаза противоречивое предложение добавить в Go отрицательные индексы как в Python. Те сейчас негативные индексы вызывают панику:
func main() {
a := []int{1, 2, 3}
fmt.Println(a[-1])
}
invalid slice index -1 (index must be non-negative)
А чтобы взять последний элемент slice’а, нужно написать так:
func main() {
a := []int{1, 2, 3}
fmt.Println(a[len(a)-1])
}
В Go 2 было предложено очередной раз добавить:
a := m[-3]
// is equivalent to
a := m[len(m)-3]
Идея не увенчалась успехом, хотя по-мнению автора это добавляет читаемость кода, что довольно спорно.
Но зато в комментариях я нашел другое предложение от Ian Lance Taylor:
> Использовать
len
без скобок для того чтобы получить последний элемент слайса:a := m[len-1]
Эту идею многие поддержали… но пока ни к чему не пришли.
P.S. Касательно
-1
и других языков программирования: хотя и в Python -1
означает len - 1
в контексте индексов списков, в JavaScript -1 всего лишь -1, а в Java - это IndexOutOfBounds. Поэтому с точки зрения читаемости кода len-1 самый понятный. to be continued…
Links:
https://github.com/golang/go/issues/33359
https://github.com/golang/go/issues/16231
https://github.com/golang/go/issues/20176
https://github.com/golang/go/issues/11245
Note #33: Разбор доклада Marwan Sulaiman - Handling Go Errors GopherCon 2019
Марван рассказывает и показывает как они обрабатывают ошибки в New York Times. Основная идея доклада в том, что у вас есть доменная модель и работать с ошибками необходимо по аналогии как Вы работаете с вашей доменной моделью. Делается это лучше всего, в виде
Вариант использование:
По сути это доклад - это пересечение двух статей [2] и [3] с примерам и подробным описанием что означает каждое поле в структуре
Данный подход помогает не только быстро понять, что и где сломалось в контексте приложения, но и легко настроить фильтры в системе логирования и мониторинга.
Если тема Вам близка то я рекомендую посмотреть видео [1] и/или прочитать еще раз эти статьи [2][3]:
Links:
[1] https://www.youtube.com/watch?v=4WIhhzTTd0Y
[2] https://middlemost.com/failure-is-your-domain/
[3] https://commandcenter.blogspot.com/2017/12/error-handling-in-upspin.html
[4] https://upspin.googlesource.com/upspin/+/master/errors/errors.go#23
Марван рассказывает и показывает как они обрабатывают ошибки в New York Times. Основная идея доклада в том, что у вас есть доменная модель и работать с ошибками необходимо по аналогии как Вы работаете с вашей доменной моделью. Делается это лучше всего, в виде
type Error struct
в пакете errors
:package Errors
// based on https://upspin.googlesource.com/upspin/+/master/errors/errors.go#23
type Error struct {
// a unique string describing a method or a function e.g. getUser
Op op
// can be predefined code/or own code (http/gRPC)
Kind kind
// you can add severity
Severity logrus.Level
// You can add any application Specific Data e.g.
ZipCode string
CreatedAt time.Time
}
Вариант использование:
if err != nil {
return &errors.Error{Op: “getUser”, Error: err}
}
По сути это доклад - это пересечение двух статей [2] и [3] с примерам и подробным описанием что означает каждое поле в структуре
Error
. Также Марван показывает несколько утилит которые помогают работать с такими ошибками (большая часть из проекта Upspin).Данный подход помогает не только быстро понять, что и где сломалось в контексте приложения, но и легко настроить фильтры в системе логирования и мониторинга.
Если тема Вам близка то я рекомендую посмотреть видео [1] и/или прочитать еще раз эти статьи [2][3]:
Links:
[1] https://www.youtube.com/watch?v=4WIhhzTTd0Y
[2] https://middlemost.com/failure-is-your-domain/
[3] https://commandcenter.blogspot.com/2017/12/error-handling-in-upspin.html
[4] https://upspin.googlesource.com/upspin/+/master/errors/errors.go#23
Note #34 Generate coverage badger in Go
Вчера нашел интересный проект https://github.com/jpoles1/gopherbadger, который позволяет генерировать картинку c процентом тестового покрытия и совместим с
P.S. также это можно сделать если у вас уже подключен
https://coveralls.io/ или https://codecov.io/
Вчера нашел интересный проект https://github.com/jpoles1/gopherbadger, который позволяет генерировать картинку c процентом тестового покрытия и совместим с
go test -cover
для вашего go пакета и умеет встраиваться сразу в README.md.P.S. также это можно сделать если у вас уже подключен
https://coveralls.io/ или https://codecov.io/
GitHub
GitHub - jpoles1/gopherbadger: Generate coverage badge images using Go!
Generate coverage badge images using Go! Contribute to jpoles1/gopherbadger development by creating an account on GitHub.
Note #35 GopherCon UK 2019 videos
Опубликовали видео с GopherCon UK 2019 🎉🍾👀
https://www.youtube.com/playlist?list=PLDWZ5uzn69ezokLCB-nGgYInxL0uP1PeZ#gopherconuk
Приятного просмотра!
P.S. позже сделаю рейтинг (top10)
Опубликовали видео с GopherCon UK 2019 🎉🍾👀
https://www.youtube.com/playlist?list=PLDWZ5uzn69ezokLCB-nGgYInxL0uP1PeZ#gopherconuk
Приятного просмотра!
P.S. позже сделаю рейтинг (top10)
Note #36 Что нас ждет в Go 1.14?! 😎
Daniel Martí выложил слайды о том, что нас ждет в Go 1.14, по сути 1 слайд 1 issue 😁
Уже можно пощупать кое-что:
Слайды https://docs.google.com/presentation/d/1HfIwlVTmVWQk94OLKfTGvXpQxyp0U4ywG1u5j2tjiuE/edit#slide=id.g550f852d27_228_0
Daniel Martí выложил слайды о том, что нас ждет в Go 1.14, по сути 1 слайд 1 issue 😁
Уже можно пощупать кое-что:
go get golang.org/dl/gotip
Слайды https://docs.google.com/presentation/d/1HfIwlVTmVWQk94OLKfTGvXpQxyp0U4ywG1u5j2tjiuE/edit#slide=id.g550f852d27_228_0
Google Docs
What's coming in Go 1.14
What's coming in Go 1.14 GoSheffield, 2019 - Daniel Martí
🇺🇦 Go for two :)
Note #35 GopherCon UK 2019 videos Опубликовали видео с GopherCon UK 2019 🎉🍾👀 https://www.youtube.com/playlist?list=PLDWZ5uzn69ezokLCB-nGgYInxL0uP1PeZ#gopherconuk Приятного просмотра! P.S. позже сделаю рейтинг (top10)
Top 10 докладов по кол-ву просмотров и лайков :)
1. GopherCon UK + GoTimeFM + LondonGophers Live
2. GopherCon UK 2019: Gergely Brautigam - Robotics with Go is a Breeze
3. GopherCon UK 2019: Gautam Rege - Impossible Go!
4. GopherCon UK 2019: Jorge Marin - Experimenting with Golang and Webassembly
5. GopherCon UK 2019: Daniela Petruzalek - Fun With Pointers
6. GopherCon UK 2019: Elias Naur - Gio Cross Platform GUI Programming for Mobile, Desktop, WebAssembly
7. GopherCon UK 2019: Ricardo Jimenez - Quicksilver How Cloudflare Controls it's Network Using Go
8. GopherCon UK 2019: Johan Brandhorst - Writing REST Services for the gRPC curious
9. GopherCon UK 2019: Joan López de la Franca Beltran - From Chaos to Domain Driven Design
10. GopherCon UK 2019: Alan Braithwaite - Advanced Testing Techniques
P.S. стоит всегда помнить, что любая конференция - это больше про нетворкинг, чем про контент или что-то новое :)
1. GopherCon UK + GoTimeFM + LondonGophers Live
2. GopherCon UK 2019: Gergely Brautigam - Robotics with Go is a Breeze
3. GopherCon UK 2019: Gautam Rege - Impossible Go!
4. GopherCon UK 2019: Jorge Marin - Experimenting with Golang and Webassembly
5. GopherCon UK 2019: Daniela Petruzalek - Fun With Pointers
6. GopherCon UK 2019: Elias Naur - Gio Cross Platform GUI Programming for Mobile, Desktop, WebAssembly
7. GopherCon UK 2019: Ricardo Jimenez - Quicksilver How Cloudflare Controls it's Network Using Go
8. GopherCon UK 2019: Johan Brandhorst - Writing REST Services for the gRPC curious
9. GopherCon UK 2019: Joan López de la Franca Beltran - From Chaos to Domain Driven Design
10. GopherCon UK 2019: Alan Braithwaite - Advanced Testing Techniques
P.S. стоит всегда помнить, что любая конференция - это больше про нетворкинг, чем про контент или что-то новое :)
Note# 37 Что делать, если Go сервисы видны наружу в интернет?
Оказывается то, что мы давно привыкли прятать сервисы за nginx(и альтернативы), Filippo Valsorda(широко известный в узких кругах по своим контрибьюшинам в Go, особоенно в пакет crypto) в своей статье[1], давно эксперементирует над тем, чтобы окрывать сервисы наружу на чистом Go (net/http, crypto/tls):
- как добавить сертификаты?
- редирект http -> https
- http/2
- добавляем таймауты и TCPKeepAlive,
- логгирование и сбор метрики,
- и огромное кол-во секьрити и не только багофиксов
Так же по его словам это вполне реально уже с go 1.8. Статья хоть и конца 2018 года, остается актуальной и сегодня...
Links:
- https://blog.cloudflare.com/exposing-go-on-the-internet/
Оказывается то, что мы давно привыкли прятать сервисы за nginx(и альтернативы), Filippo Valsorda(широко известный в узких кругах по своим контрибьюшинам в Go, особоенно в пакет crypto) в своей статье[1], давно эксперементирует над тем, чтобы окрывать сервисы наружу на чистом Go (net/http, crypto/tls):
- как добавить сертификаты?
- редирект http -> https
- http/2
- добавляем таймауты и TCPKeepAlive,
- логгирование и сбор метрики,
- и огромное кол-во секьрити и не только багофиксов
Так же по его словам это вполне реально уже с go 1.8. Статья хоть и конца 2018 года, остается актуальной и сегодня...
Links:
- https://blog.cloudflare.com/exposing-go-on-the-internet/
The Cloudflare Blog
So you want to expose Go on the Internet
Back when crypto/tls was slow and net/http young, the general wisdom was to always put Go servers behind a reverse proxy like NGINX. That's not necessary anymore!
Note #38 Go time 102: Application design 📻🎤
В этому выпуске Kat Zień, Peter Bourgon и Ben Johnson обсуждают тему, которая затрагивает каждый Go проект: как лучше всего организовать проект.
Краткое содержание интересных идей из эпизода:
1) выбираем структуру проекта в зависимости от вашего приложения/контекста, полезно лишний раз обсуждать с коллегами
2) никогда не используем “Global state”
3) Используем io.Reader/io.Writer вместо os.Stdout/os.Stdin для того, чтобы передавать buffer в тестах, тем самым контролировать поток ввода/вывода и логирование.
4) tiny main abstraction
6) Пишем код который легко удалить, а не тот который легко расширить. 🔪
7) Не следует писать код - лишь бы удовлетворить компилятор, помним: мы пишем код для людей.
8) Фокусируемся на happy path, если пользователь что-то покупает - самое главное это как можно быстрее вернуть результат об успешной транзакции, а не упасть из-за того что лого не подгрузилось или email не отправился.
9) Начинаем с кода который выполняется последовательно и только позже добавляем concurrency.
P.S. От себя добавлю, что очень часто просматриваю как организованы чужие проекты на github. Например недавно, пересмотрел как организованы такие консольные утилиты как (docker, kubectl, helm3, doctl и так далее), что очень часто помогает выбрать наиболее удачную структуру.
https://changelog.com/gotime/102
В этому выпуске Kat Zień, Peter Bourgon и Ben Johnson обсуждают тему, которая затрагивает каждый Go проект: как лучше всего организовать проект.
Краткое содержание интересных идей из эпизода:
1) выбираем структуру проекта в зависимости от вашего приложения/контекста, полезно лишний раз обсуждать с коллегами
2) никогда не используем “Global state”
3) Используем io.Reader/io.Writer вместо os.Stdout/os.Stdin для того, чтобы передавать buffer в тестах, тем самым контролировать поток ввода/вывода и логирование.
4) tiny main abstraction
func main() {5) Пишем только то, что нужно прямо сейчас.
if err := run(); err != nil {
fmt.FPrintf(os.Stderr, "%s\n", err)
os.Exit(1)
}
}
// dummy
func run() error {
return nil
}
6) Пишем код который легко удалить, а не тот который легко расширить. 🔪
7) Не следует писать код - лишь бы удовлетворить компилятор, помним: мы пишем код для людей.
8) Фокусируемся на happy path, если пользователь что-то покупает - самое главное это как можно быстрее вернуть результат об успешной транзакции, а не упасть из-за того что лого не подгрузилось или email не отправился.
9) Начинаем с кода который выполняется последовательно и только позже добавляем concurrency.
P.S. От себя добавлю, что очень часто просматриваю как организованы чужие проекты на github. Например недавно, пересмотрел как организованы такие консольные утилиты как (docker, kubectl, helm3, doctl и так далее), что очень часто помогает выбрать наиболее удачную структуру.
https://changelog.com/gotime/102
Changelog
On application design with Peter Bourgon, Kat Zień & Ben Johnson (Go Time #102)
Mat is joined by Peter Bourgon, Kat Zień, and Ben Johnson to talk about application design in Go — principles, trade-offs, common mistakes, patterns, and the things you should consider when it comes to application design.
Note #39 Import declaration 3 times
Сегодня наткнулся на интересный пример, если импортировать пакет 3 раза:
Что же тут интересного скажете Вы?!
- Go не запрещает импортировать один и тот же пакет если вы присваиваете каждому из них уникальный алиас. [1]
- Даже если вы импортируете пакет
- Пакет будет доступен по всем 3 алиасам как показано в примере выше.
Реальный пример, где это может пригодиться, есть метод в параметрах которой есть
P.S. Я видел такой трюк несколько раз, и удивился, что это стало находкой для Brad Fitzpatrick [2] в PR об удалении переменной parseURL [3].
Links:
[1] https://golang.org/ref/spec#Import_declarations
[2] https://twitter.com/bradfitz/status/1186368288797777920
[3] https://go-review.googlesource.com/c/go/+/202482
Сегодня наткнулся на интересный пример, если импортировать пакет 3 раза:
package main
import "math" // math.Sin
import m "math" // m.Sin
import k "math" // k.Sin
func main() {
print(math.Pi, m.Pi, k.Pi)
}
Что же тут интересного скажете Вы?!
- Go не запрещает импортировать один и тот же пакет если вы присваиваете каждому из них уникальный алиас. [1]
- Даже если вы импортируете пакет
math
3 раза, то он будет импортироваться только 1 раз- Пакет будет доступен по всем 3 алиасам как показано в примере выше.
Реальный пример, где это может пригодиться, есть метод в параметрах которой есть
path
и также path
имя пакета который нам нужен внутри функции:import (
"path"
pathpkg "path"
)
func (ld *loader) stdVendor(parentPath, path string) string {
// missing few lines here
vendorPath := pathpkg.Join("cmd", "vendor", path)
// missing few lines here
P.S. Я видел такой трюк несколько раз, и удивился, что это стало находкой для Brad Fitzpatrick [2] в PR об удалении переменной parseURL [3].
Links:
[1] https://golang.org/ref/spec#Import_declarations
[2] https://twitter.com/bradfitz/status/1186368288797777920
[3] https://go-review.googlesource.com/c/go/+/202482
Note #40 gops - list of your go process currently running
Нашел отличный тул
С помощью
Больше примеров как обычно в README [1]
Links:
[1] https://github.com/google/gops
Нашел отличный тул
gops
, которые показывает список Go процессов, которые сейчас запущены.$ go get -u github.com/google/gops
С помощью
gops
легко посмотреть версию Go бинарника который сейчас запущен:$ gops
64186 81994 gops go1.13 /Users/andrii/workspace/bin/gops
76 1 com.docker.vmnetd go1.12.7 /Library/PrivilegedHelperTools/com.docker.vmnetd
….
$ gops tree
├── 81994
│ └── 70280 (gops) {go1.13}
├── 1
│ ├── 76 (com.docker.vmnetd) {go1.12.7}
│ ├── 28657 (updater) {go1.13}
│ ├── 28669 (kbfs) {go1.13}
│ └── 28663 (keybase) {go1.13}
├── 5099
│ ├── 5106 (com.docker.backend) {go1.12.7}
│ └── 5104 (com.docker.driver.amd64-linux) {go1.12.7}
└── 5032
Больше примеров как обычно в README [1]
Links:
[1] https://github.com/google/gops
GitHub
GitHub - google/gops: A tool to list and diagnose Go processes currently running on your system
A tool to list and diagnose Go processes currently running on your system - google/gops
Note #41: Поиск по исходному коду Go 🏄♂️
Итак что умеет
💥Поиск числа 255 в разных системах счисления (0b1111_1111, 0377, 0o377, 255, 0xff) во всех *.go файлах в текущей директории:
💥Поиск по всем комментариям, которые содержат слово
💥Поиск по всем ключевым словам, в частности по ifaм:
Болеше инфы как обычно в help. Have fun!
P.S. Также рекомендую познакомиться с аналогами
Useful links:
https://github.com/MichaelTJones/gg
https://github.com/BurntSushi/ripgrep
https://github.com/monochromegane/the_platinum_searcher
https://github.com/ggreer/the_silver_searcher
gg
- еще один аналог старичка grep
, который сужает поиск только: по ключевым словам, комментариям, и различным литералам.Итак что умеет
gg
:💥Поиск числа 255 в разных системах счисления (0b1111_1111, 0377, 0o377, 255, 0xff) во всех *.go файлах в текущей директории:
gg v 255 .
💥Поиск по всем комментариям, которые содержат слово
case
и игнорирует конструкцию switch case
:gg c case .
💥Поиск по всем ключевым словам, в частности по ifaм:
gg k if .
Болеше инфы как обычно в help. Have fun!
P.S. Также рекомендую познакомиться с аналогами
grep
заточенных под разработчиков: ripgrep
(Rust), pt
(platinum searcher) или ag
(silver searcher) и ack
eсли вы еще не слышали о них.Useful links:
https://github.com/MichaelTJones/gg
https://github.com/BurntSushi/ripgrep
https://github.com/monochromegane/the_platinum_searcher
https://github.com/ggreer/the_silver_searcher
Note #42 Proposal: Scaling the Go page allocator
Пока мы все читали пропозалы про Go2, ошибки и дженерики ребята написали предложение, о том чтобы потюнить Go runtime page аллокатор, который содержит серьезные проблемы с маштабирование при высоких hit rate аллокациях и большом GOMAXPROCS=32.
Заметили проблему в kubernetes/kubernetes/issues/75833 и в issue golang/go/28479 (runtime: make([]byte, n) becomes much slower compared with go 1.11.1)
В общем все детали в достаточно объемном документе:
https://go.googlesource.com/proposal/+/refs/changes/57/202857/2/design/35112-scaling-the-page-allocator.md
Оригинальный issue: https://github.com/golang/go/issues/35112
P.S. Thanks @o8tomat8o за ссылку.
Пока мы все читали пропозалы про Go2, ошибки и дженерики ребята написали предложение, о том чтобы потюнить Go runtime page аллокатор, который содержит серьезные проблемы с маштабирование при высоких hit rate аллокациях и большом GOMAXPROCS=32.
Заметили проблему в kubernetes/kubernetes/issues/75833 и в issue golang/go/28479 (runtime: make([]byte, n) becomes much slower compared with go 1.11.1)
В общем все детали в достаточно объемном документе:
https://go.googlesource.com/proposal/+/refs/changes/57/202857/2/design/35112-scaling-the-page-allocator.md
Оригинальный issue: https://github.com/golang/go/issues/35112
P.S. Thanks @o8tomat8o за ссылку.