id := r.URL.Query()["id"]
var (y = "hello")
var (
x = 1
y int32 = 3
z = somelib.NewValue()
)
const(
a = 1
b = 2
c = 3
)
type(
Alias map[string]int
Collector interface{
...
}
Point struct{
...
}
)
Зачем?
Зачем оператор :=?
func someVals() int, int{
return 5, 10
}
a, b := someVals()
// Так нельзя.
var a, b = someVals()
// Только так.
var a,b int
a, b = someVals()
// Еще для этого.
if val, ok := somemap["key"]; ok {
...
}
for i := 0; i < N; i ++{
}
А массивы и срезы? Зачем несколько способов создания?
// выделяем на куче массив длины 5, емкости 10
// обычно выделяют массив с заданной длиной 0, и необходимой емкостью,
// чтобы без выделения памяти делать append()
// да и make возвращает срез, а не массив.
x := make([]int, 5, 10)
// Тут вы определяете массив длины 5 с заданными значениями.
// По сути вы создаете тип [5]int.
arr := [5]int{1,2,3,4,5}
// Тут вы уже взяли срез.
// Срез это не массив.
x := arr[0:5]
var x map[string]int
x["key"] = 10
// А еще он делает и каналы (про них вы еще не прочитали? ) ).
x := make(map[int]int)//простите а почему make делает карты и массивы?
// Вы искренне не понимаете для чего этот вариант?
var x map[int]int{1:1}
отсутствие перегрузки функций
дженериков
утиная типизация
а вечное if err != nil через строчку?
Из за отсутствия сахара го является одним из самых многословных языков, которые я видел.
Например, я передаю через контекст еще дополнительно и логгер с параметрами запроса.
context.TODO() предполагает, что потом будет передаваться контекст с более верхнего уровня по цепочке, если это не так, то используется context.Background().
ну как дополнительный пример - мой стандартный паттерн при работе с горутинами и каналами влючает в себя контроль выполнения через контекст: