21.1 Основы Golang
Философия Go
Какие проблемы решает
- Медленная сборка программ
- Неконтролируемые зависимости
- Использования разными программистами разных подмножеств языка
- Затруднения с пониманием программ
- Сложность разработки инструментария
Специфика
- Мало сахара (один способ решить задачу)
- Быстрая компиляция
- Нет эксепшенов
- Очень ограниченное число операций
- Поддержка указателей без арифметики над ними
Переменные
| var v1 int
fmt.Println(v1)
var v2 int = 100
v3 := 5
var v5, v6 = 1,2
v5,v6 = 3,4
var (
v01 = 1
v02 = "string"
)
# Игнорирование переменных
_ = v01
|
Константы
Указатели
Переменные это блок памяти в которой хранятся наши данные
Значением указателя - является адрес этого блока памяти
| x := 1
ptr := &x
*ptr = 5
|
Синонимы числовых типов
| type rune = int32 // Представляет собой unicode символ
type byte = uint8
|
Числа с плавающей точкой
| float32 // точность 6 знаков после запятой
float64 // точность 15 знаков после запятой
|
Строки
Строка это неизменяемая последовательность байтов
| var myString string
word := "my string"
var b byte = 'c' // равно 99 - восьмибитное представление
var r rune = '你' // равно 20320 - Полноценное utf8 представление
str = "some text."
fmt.Println(len(str)) // 9 - Количество БАЙТ! в строке
fmt.Println(str[1]) // 111
|
Составные типы
Массивы
Последовательность фиксированной длины
| var x1 [5]int
var arr [3]int = [3]int{1,2,3}
var arr2 = [3]int{1,2,3}
arr3 := [3]int{1,2,3}
arr3 = [2]int{1,2} // Ошибка - нельзя присвоить 2 значением
arr5 := [...]int32{1,2,3,4,5}
|
Slice
Последовательность переменной длины
Под капотом у срезов лежат массивы
Емкость среза это предел до конца массивы
| var list []string
list = []int64{1,2,3,4,5}
l = len(list) // 5
c = cap(list) // 5
list = make([]int64, 0, 5])
l = len(list) // 0
c = cap(list) // 5
list = make([]int64, 5, 5]) // [0,0,0,0,0]
l = len(list) // 5
c = cap(list) // 5
list = []int64{1,2,3,4}
// Функция append len увеличивается на 1,
// если больше cap то создается новый массив и значение переносится туда
list = append(list, 5)
l = len(list) // 5
c = cap(list) // 8
|
Map
| var m1 map[int32]bool
m3 := make(map[int]int)
ages := map[string]int {
"Mike": 30,
"Jon": 24,
// ...
}
age := ages["Mike"] // 30
ages["Bob"] = 31
// Вывод значения которого не существует
fmt.Println(ages["Max"]) // 0
ages["Max"]++ // ["Max": 1]
|
Struct
Агрегированный тип данных
| type Point struct {
X int
Y int
Z int
T []int64
}
p = Point{5, 15}
fmt.Println(p.X)
p.X = 55
|
Функции
| func addPrefix(origin string) string {
return "prefix_" + origin
}
func addPrefixWithLen(origin string) (res string, length int) {
// На этапе начала функции переменные уже получат дефолтные значения
res = "prefix_" + origin
length = len(res)
return res, length
}
|
Анонимные функции
| f := func() {...}
s := strings.Map(func(r rune) rune {return r + 1}, "TEXT")
|
Отложенный вызов функции DEFER
Аргументы вычисляются на момент объявления defer, но фактический вызов будет отложен
Defer - если несколько то выполняются в обратном порядке
Циклы и условные операторы
| if a == 5 {
// pass
}
switch a {
case 1:
// pass
default:
// pass
}
switch {
case a > 1 || b < 10:
// pass
default:
// pass
}
|
Циклы
| for {
// бесконечный цикл
}
for a == 5 {
// pass
}
for i := 0; i < 10; i++ {
// pass
}
sl := []int64{1,2,3}
for key, value := range sl {
fmt.Printf("key: %v, val: %v \n", key, value)
}
word := "привет"
for i := 1; i < len(word); i++ {
fmt.Printf("%T", word[i]) // Выводит байты
}
for key, value := range word {
fmt.Println(value) // Выводит rune
}
|
Структуры
Поля структуры
| // new - встроенная в язык функция которая возвращает адрес на выделенную память
i := new(int64)
type Avatar struct {
URL string
Size int64
}
type Client struct {
ID int64
Name string
Age int
IMG *Avatar
}
func updateAvatar(client Client){
client.IMG.URL = "updated_url"
}
client := Client{} // Будут присвоены все дефолтные поля
updateAvatar(client) // Не правильно, передача по значению!
////////
func updateAvatar(client *Client){
client.IMG.URL = "updated_url"
}
client := Client{}
// client.IMG = new(Avatar)
client.IMG = &Avatar{}
updateAvatar(&client) // Правильно
|
Методы структуры
Привязка типа с указанием роли получателя
| finc (p Point) myMethod (param int) string {
// pass
}
func (c Client) HasAvatar() bool {
if c.IMG != nil && c.IMG.URL != "" {
return true
}
return false
}
func (c Client) UpdateAvatar() {
c.IMG.URL = "new_url"
}
func main() {
client := Client{
ID: 7,
Name: "Bob",
Age: 20,
IMG: &Avatar{
URL: "test",
},
}
fmt.Printf("%#v", client)
fmt.Println(client.HasAvatar())
}
|