// Целочисленные типы
int8 | -128 | 127
int16 | -32768 | 32767
int | -2147483648 | 2147483647
int32 | -2147483648 | 2147483647
int64 | -9223372036854775808 | 9223372036854775807
// Беззнаковые целые типы
uint8 | 0 | 255
byte | 0 | 255
uint16 | 65535
uint | 4294967295
uint32 | 4294967295
uint64 | 18446744073709551615
// Другие типы данных
float32
float64
complexes
complex128
// Псевдонимы
type UserId int
type Speed float64
type Velocity Speed
// Преобразование типа
UserId(5)
Speed(88.3)
// Создание рун и строк
myRune := 'Q'
fmt.Println(myRune) // Выведет 81, что в 16-тиричной ситеме равно 0x51
myString := "This is my string"
fmt.Println(myString) // Выведет "This is my string"
myRawString := `This is my raw \nstring`
fmt.Println(myRawString) // Выведет "This is my raw \nstring" (проигнорирует символ переноса)
var varWithoutTypeAnnotation = 1
var varWithTypeAnnotation int = 2
var varWithDefinitionOnly int // Здесь переменная получает значение по-умолчанию = 0
varWithDefinitionOnly = 3
var a, b, c = 1, 2, "My var is C"
var (
x = 1
y = "My var is Y"
)
myVarWithDefAndInit := 100
// Здесь не будет ошибки!
myVar1, myError := 1, 0
myVar2, myError := 2, 0
func mySum(x, y int) (int, string) {
return x + y, "success"
}
func main() {
ret, _ := mySum(1, 2)
fmt.Println(ret)
}
// Арифметические
+
-
*
/
%
+=
-=
*=
/=
%=
i++
i--
// Сравнение
<
<=
>=
>=
!=
// Логические
&& (И)
|| (ИЛИ)
! (НЕ)
// Множественные условия
a := 5
if a > 0 && a < 100 {
fmt.Println("Positive")
} else if a == 0 {
fmt.Println("Zero")
} else {
fmt.Println("Negative")
}
// Инициализация переменной в условии
if a := 100; a > 0 {
fmt.Println("Positive")
}
// Switch
a := 2
switch a {
case 1:
fmt.Println("One")
case 2:
fmt.Println("Two")
default:
fmt.Println("Default")
}
// Switch с вызовом функции
func mySum(x, y int) int {
return x + y
}
func main() {
switch res := mySum(1, 1); {
case res > 0:
fmt.Println("Positive")
case res == 0:
fmt.Println("Zero")
default:
fmt.Println("Negative")
}
}
// Множественные условия в switch
x := 2
switch x {
case 1, 2, 3:
fmt.Println("Positive")
case -1, -2, -3:
fmt.Println("Negative")
}
// Switch с fallthrough (падение в следующий блок кода)
x := 1
switch x {
case 1:
fmt.Println("Positive”) // Выполнится
fallthrough
case 2:
fmt.Println("Negative") // Также выполнится!
case 3:
fmt.Println("Negative")
}
// Стандартный цикл
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// Цикл с инкрементом внутри тела
i := 0
for i < 10 {
fmt.Println(i)
i++
}
// Бесконечный цикл c прерыванием (break)
somethingHappened := true
for {
if somethingHappened {
break
}
}
// Цикл с пропуском части элементов
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue
}
fmt.Println(i)
}
// Структура немного похожа на класс
// Создание структуры
type MyStruct struct {
myStringField string
myIntField int
}
myStructDefault := MyStruct{}
myStructHalfDefault := MyStruct{myIntField: 5}
myStruct1 := MyStruct{"string", 5}
myStruct2 := MyStruct{myStringField: "string", myIntField: 5}
// Использование структуры
myString := myStruct1.myStringField
myString, myInt := myStruct1.myStringField, myStruct1.myIntField
// Анонимные структуры
myVar := struct {
a string
b int
}{
"hello",
5,
}
// Создание массива
arr10 := [10]int{} // 0 0 0 0 0 0 0 0 0 0
arr5 := [5]int{1, 2, 3, 4, 5} // 1 2 3 4 5
arr3 := [...]int{1, 2, 3} // 1 2 3
arr6 := [6]int{1, 1, 1, 1, 1} // 1 1 1 1 1 0(default!)
// Задание значений массива
arr10[0] = 777 // 777 0 0 0 0 0 0 0 0 0
// Перебор массива в цикле
for key, value := range arr10 {
fmt.Println(key, value)
}
// Создание массива
myArray := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // [1 2 3 4 5 6 7 8 9 10]
// Создание срезов из массива
slice_0_4 := myArray[:5] // [1 2 3 4 5]
slice_5_9 := myArray[5:10] // [6 7 8 9 10]
// Создание и расширение среза
mySlice := []int{1, 2, 3} // [1 2 3]
mySlice = append(mySlice, 4) // [1 2 3 4]
myAnotherSlice := []int{7, 7, 7} // [7, 7, 7]
mySlice = append(mySlice, myAnotherSlice...) // [1, 2, 3, 4, 7, 7, 7]
// Предварительное выделение памяти под срез
// Известно количество элементов заранее, но не сами элементы
myUnknownSlice := make([]int, 10) // [0 0 0 0 0 0 0 0 0 0]
// Многомерные срезы (поля для игры Крестики-нолики)
board := [][]string{{"_", "_", "_"}, {"_", "_", "_"}, {"_", "_", "_"}}
board[0][0] = "X"
board[0][2] = "O" // [[X _ O] [_ _ _] [_ _ _]]
// Неупорядоченный тип данных!
// Создание мапы через make
myMap := make(map[string]int) // map[]
// Создание непустой мапы
myFilledMap := map[int]string{0: "Zero", 1: "One", 2: "Two"}
fmt.Println(myMap)
fmt.Println(myFilledMap) // map[0:Zero 1:One 2:Two]
// Операции с мапами
// 1. Добавить элемент
myMap["One"] = 1 // map[One:1]
myMap["Two"] = 2 // map[One:1, Two:2]
// 2. Получить значение по ключу
one := myMap["One"] // 1
// 3. Удалить пару по ключу
delete(myMap, "One") // map[Two:2]
// 4. Проверить наличие ключа в мапе
item, found := myMap["Two"] // item: 2, found: true
if !found {
fmt.Println("item not found")
return
}
item, found = myMap["One"] // item: 0, found: false
// Итерация по элементам мапы
for key, value := range myFilledMap {
fmt.Println(key, value)
} // 2 Two, 0 Zero, 1 One
myVar := 10
// Создаем указатель
var myPtr *int
myPtr = &myVar // 0xc000104020
// Создаем указатель (краткая форма)
myAnotherPtr := &myVar
// Получаем значение переменной из указателя
value := *myPtr // 10
// Использование указателя в функции
func myInc(x *int) {
*x++
}
func main() {
myVar := 10 // 10
myInc(&myVar) // 11
myInc(&myVar) // 12
}
// 1. Методы с указателем на структуру
type Calculator struct {
result int
}
// Из метода не нужно возвращать значение, т к работаем с указателем
func (calculator *Calculator) add(x, y int) {
calculator.result = x + y
}
func main() {
calc := Calculator{}
calc.add(2, 3)
res := calc.result // 5
}
// 2. Методы с оригинальной структурой (без указателя)
type Calculator struct {
result int
}
func (calculator Calculator) add(x, y int) Calculator {
calculator.result = x + y
// Возвращаем структуру
return calculator
}
func main() {
calc := Calculator{}
calc = calc.add(2, 3)
res := calc.result // 5
}
// Обычные константы
const MaxSpeed = 30
MaxSpeed = 40 // Ошибка!
// Аналог создания констант с использованием ключевого слова iota
// iota - используется для автоматического задания значений констант (часто групповых)
const (
Undefined = iota
Draft
Active
) // 0, 1, 2
// Сдвиг начала + пропуски
const (
Undefined = iota + 3
_
Draft
Active
) // 3, 5, 6
// Печать в терминал
Printf - печатает отформатированный текст с вербами и аргументами
Print - печатает текст без форматирования
Println - печатает отформатированный текст + добавляет символ перевода строки в конце
// Печать в поток данных
Fprintf
Fprint
Fprintln
// Печать в строку
Sprintf
Sprint
Sprintln
// Примеры использования
name := "Tatyana"
age := 25
fmt.Printf("Hello, %v! You are %v years old\n", name, age)
fmt.Println("Hello,", name, "! You are", age, "years old")
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestMaps(t *testing.T) {
expectedMap := map[string]int{"a": 1, "b": 2, "c": 3}
t.Logf("Expected: %v", expectedMap)
actualMap := map[string]int{"i_am_different": 0, "b": 2, "c": 3}
t.Logf("Actual: %v", actualMap)
assert.Equal(t, expectedMap, actualMap)
}