CLI §
go version
# Build or run single file:
go build main.go
go clean main.go
go run main.go
# Init Go module in the current directory:
go mod init tools
# Run project in current directory:
go run .
go doc
go fmt
go get
go install
go help
go test
# Detect problems:
go vet
Сборка для конкретной ОС §
Список поддерживаемых ОС: https://go.dev/src/go/build/syslist.go
# Указать целевую систему в переменной окружения и выполнить сборку:
GOOS = windows go build
Basic program structure §
// Each code file has to declare package to which its contents belong:
package main
// Declare dependency on built-in package
import "fmt"
// `main()` in the main package is the program's entry point
func main() {
fmt.Println("Hello, Go world!")
for i := 0; i < 5; i++ {
fmt.Println(i)
}
}
NB: by convention, semicolons are omitted in Go code, althought might be used.## Работа со строками
…
Слайсы §
Объединение слайсов §
Чтобы соединить два слайса, нужно распаковать слайс append(a,b...)
. Функция принимает некоторое количество отдельных элементов и преобразует слайс в список через распаковку.
Сортировка §
s := [] int { 5 , 4 , 1 , 3 , 2 }
sort. Ints (s)
fmt. Println (s) // [1 2 3 4 5]
Функция sort.Ints
сортирует полученный слайс целых чисел по возрастанию. Она не меняет размер и ёмкость слайса, поэтому может спокойно работать с ним.
Копирование слайсов §
Для копирования элементов из одного слайса в другой применяется функция copy([]T dest, []T src)
, где dest
— это слайс-приёмник, а src
— слайс-источник. Эта функция только перезаписывает элементы, поэтому количество скопированных элементов будет равно меньшей длине из двух слайсов.
var dest [] int
dest2, dest3 := make ([] int , 3 ), make ([] int , 5 )
src := [] int { 1 , 2 , 3 , 4 }
copy (dest, src)
copy (dest2, src)
copy (dest3, src)
fmt. Println (dest, dest2, dest3, src ) // [] [1 2 3] [1 2 3 4 0] [1 2 3 4]
Удаление последнего элемента слайса §
s := [] int { 1 , 2 , 3 }
if len (s) != 0 { // защищаемся от паники
s = s[: len (s) - 1 ]
}
fmt. Println (s) // [1 2]
Удаление первого элемента слайса §
s := [] int { 1 , 2 , 3 }
if len (s) != 0 { // защищаемся от паники
s = s[ 1 :]
}
fmt. Println (s) // [2 3]
Удаление элемента слайса с индексом i
§
s := [] int { 1 , 2 , 3 , 4 , 5 }
i := 2
if len (s) != 0 && i < len (s) { // защищаемся от паники
s = append (s[:i], s[i + 1 :] ... )
}
fmt. Println (s) // [1 2 4 5]
Сравнение двух слайсов §
s1 := [] int { 1 , 2 , 3 }
s2 := [] int { 1 , 2 , 4 }
s3 := [] string { "1" , "2" , "3" }
s4 := [] int { 1 , 2 , 3 }
fmt. Println (reflect. DeepEqual (s1,s2)) // false
fmt. Println (reflect. DeepEqual (s1,s3)) // false
fmt. Println (reflect. DeepEqual (s1,s4)) // true
Misc §
https://ueokande.github.io/go-slice-tricks/
Работа со строками §
Удаление пробелов в начале и конце строки §
import (
" bytes "
" fmt "
)
func main () {
bSlice := [] byte ( " \t\n a lone gopher \n\t\r\n " )
fmt. Printf ( " %s " , bytes. TrimSpace (bSlice)) // a lone gopher
fmt. Printf ( " %s " , bSlice) // \t\n a lone gopher \n\t\r\n
}
Функция bytes.TrimSpace
принимает слайс байт и возвращает новый слайс байт, откуда были удалены начальные и конечные пробельные символы. Размер слайса должен измениться, а значит, bSlice
останется нетронутым. В итоге bytes.TrimSpace
подарит нам новый слайс.
Взаимодействие с ОС §
Чтение и установка переменных окружения §
envLockboxFileName := os. Getenv (envVarWithFileName)
os. Setenv (envVarWithFileName, lockboxFileName)
Рекурсивный обход всех файлов и директорий §
package main
import (
" fmt "
" os "
" path/filepath "
)
func main () {
PrintAllFiles ( "." )
}
func PrintAllFiles (path string ) {
// получаем список всех элементов в папке (и файлов, и директорий)
files, err := os. ReadDir (path)
if err != nil {
fmt. Println ( "unable to get list of files" , err)
return
}
// проходим по списку
for _, f := range files {
// получаем имя элемента
// filepath.Join — функция, которая собирает путь к элементу с разделителями
filename := filepath. Join (path, f. Name ())
// печатаем имя элемента
fmt. Println (filename)
// если элемент — директория, то вызываем для него рекурсивно ту же функцию
if f. IsDir () {
PrintAllFiles (filename)
}
}
}
Замыкания (closures) §
Итератор на замыканиях §
func Generate (seed int ) func () {
return func () {
fmt. Println (seed) // замыкание получает внешнюю переменную seed
seed += 2 // переменная модифицируется
}
}
func main () {
iterator := Generate ( 0 )
iterator ()
iterator ()
iterator ()
iterator ()
iterator ()
}
Работа с файлами §
…
Работа с JSON §
Marshal struct
to JSON §
type Person struct {
Name string `json:"Имя"`
Email string `json:"Почта"`
DateOfBirth time.Time `json:"-"` // - означает, что это поле не будет сериализовано
}
func main () {
man := Person{
Name: "Alex" ,
Email: "alex@yandex.ru" ,
DateOfBirth: time. Now (),
}
jsMan, err := json. Marshal (man)
if err != nil {
log. Fatalln ( "unable marshal to json" )
}
fmt. Printf ( "Man %v " , string (jsMan)) // Man {"Имя":"Alex","Почта":"alex@yandex.ru"}
}
Unmarshal JSON string to struct
§
package main
import (
" encoding/json "
" fmt "
)
const rawResp = `
{
"header": {
"code": 0,
"message": ""
},
"data": [{
"type": "user",
"id": 100,
"attributes": {
"email": "bob@yandex.ru",
"article_ids": [10, 11, 12]
}
}]
}
`
type (
Response struct {
Header ResponseHeader `json:"header"`
Data ResponseData `json:"data,omitempty"`
}
ResponseHeader struct {
Code int `json:"code"`
Message string `json:"message,omitempty"`
}
ResponseData []ResponseDataItem
ResponseDataItem struct {
Type string `json:"type"`
Id int `json:"id"`
Attributes ResponseDataItemAttrs `json:"attributes"`
}
ResponseDataItemAttrs struct {
Email string `json:"email"`
ArticleIds [] int `json:"article_ids"`
}
)
func ReadResponse (rawResp string ) (Response, error ) {
resp := Response{}
if err := json. Unmarshal ([] byte (rawResp), & resp); err != nil {
return Response{}, fmt. Errorf ( "JSON unmarshal: %w " , err)
}
return resp, nil
}
func main () {
resp, err := ReadResponse (rawResp)
if err != nil {
panic (err)
}
fmt. Printf ( " %+v\n " , resp)
}
CI/CD pipeline §
name : Go CI/CD Pipeline
on :
push :
branches :
- main
jobs :
build :
runs-on : ubuntu-latest
steps :
- name : Checkout repository
uses : actions/checkout@v2
- name : Set up Go
uses : actions/setup-go@v2
with :
go-version : 1.17
- name : Build
run : go build -v ./...
- name : Test
run : go test -v ./...
deploy :
runs-on : ubuntu-latest
needs : build
if : github.ref == 'refs/heads/main'
steps :
- name : Deploy to server
run : |
# Add deployment script here
Алгоритмы §
Примеры реализации популярных алгоритмов на Go.
Quicksort §
Пример мой, возможно – не лучший.
// Quicksort algorithm demo
package main
import " fmt "
// SortNumbers ...
// Sort `numbers` using quicksort algorithm
func SortNumbers (numbers [] int ) [] int {
if numbers == nil {
return [] int {}
}
if len (numbers) < 2 {
return numbers
}
pivot := numbers[ 0 ]
var less [] int
var more [] int
for _, i := range numbers[ 1 :] {
if i <= pivot {
less = append (less, i)
} else {
more = append (more, i)
}
}
return append ( append ( SortNumbers (less), pivot), SortNumbers (more) ... )
}
func main () {
array := [] int { 99 , 88 , 77 , 66 , 55 , 44 , 33 , 22 , 11 }
fmt. Println ( SortNumbers (array))
}
Пример рекурсивного вычисления n!
, факториала числа §
func fact (n int ) int {
if n == 0 { // терминальная ветка — то есть условие выхода из рекурсии
return 1
} else { // рекурсивная ветка
return n * fact (n - 1 )
}
}
Числа Фибоначчи §
func Fib (n int ) int {
switch {
case n <= 1 : // терминальная ветка
return n
default : // рекурсивная ветка
return Fib (n - 1 ) + Fib (n - 2 )
}
}
📂 Рецепты | Последнее изменение: 25.08.2024 10:59