Какво са масивите в Go?
Могат ли да имат променлива дължина?
Какво е range?
Как са имплементирани слайсовете в Go?
len) определя този слайс каква част от масива вижда.
arr := [6]float64{1,2,3,4,5,6}
x := arr[1:]
slice1 := append(x, 4)
Какви типове имат arr, x, slice1?
Какво ще върнат len(x), cap(x), len(slice1), cap(slice1)?
Какво прави този код:
var x map[string]int
x["key"] = 10
if name, ok := x["key"]; ok {
fmt.Println(name, ok)
}
Каква е разликата между new и make и кога се ползва едното, и кога другото?
new само заделя памет и я нулира, за разлика от make, което инициализира обекта. new ползваме за наши типове (структури), make само за слайсове и хешове. new връща указател, make връща стойност.type integer int type float float64 type chars string
func Abs(i integer) integer {
switch {
case i < 0:
return -i
case i == 0:
return 0
default:
return i
}
}
var number integer = -42
positiveInteger := Abs(number)Abs, която се извиква като ѝ се подаде integer като аргументfunc (i integer) Abs() integer {
switch {
case i < 0:
return -i
case i == 0:
return 0
default:
return i
}
}
var number integer = -42
number.Abs()
* По стойност
- Работи се върху копие на обекта
- Това може да е скъпа операция за големи обекти
* Като указател
- Работи се върху самия обект
- Всяка промяна в метода се отразява на оригиналния обект
package main
import "fmt"
type integer int func (i integer) Abs() integer { switch { case i < 0: return -i case i == 0: return 0 default: return i } } func (i *integer) Increment() { *i++ } func main() { var number integer number = -42 number.Increment() fmt.Println(number.Abs())
}
type Rectangle struct {
x, y int
}
type Triangle struct {
x, y, z int
}func (r *Rectangle) Circumference() int {
return 2 * (r.x + r.y)
}
func (r *Triangle) Circumference() int {
return r.x + r.y + r.z
}Circumference()
type Shape interface {
Circumference()
}Circumference със същата сигнатура, имплементира ShapeTriangle и Rectangle имплицитно го имплементиратpackage main
import "fmt"
type Shape interface {
Circumference() int
}
type Rectangle struct {
x, y int
}
func (r *Rectangle) Circumference() int {
return r.x + r.y
}
type Triangle struct {
x, y, z int
}
func (t *Triangle) Circumference() int {
return t.x + t.y + t.z
}
func sumOfCircumferences(shapes ...Shape) int { sum := 0 for _, shape := range shapes { sum += shape.Circumference() } return sum }
func main() {
rect := &Rectangle{x: 12, y: 64}
tr := &Triangle{x: 12, y: 64, z: 50}
fmt.Println(sumOfCircumferences(rect, tr))
}
Конструираме един тип, комбинирайки няколко прости други типa.
* Пример:
Искаме да си направим smartphone. Не откриваме топлата вода, а просто го наблъскваме с каквито джаджи се сетим.
type Smartphone struct {
phone BasicPhone
camera CameraModule
wifi WiFiModule
screen MultiTouchScreen
battery DamnHugeBattery
}Всеки един от тези типове отговаря за точно едно нещо и може да бъде използвано самостоятелно.
Вярваме, че знаете как работи то. Дори сме сигурни, че сте правили хора и студенти:
type Student struct {
Person
facultyNumber int16
}Вложеният тип, е анонимен, което присвоява всичките му методи и атрибути на базовия клас.
Да, имате право на много анонимни вложени типа. Не го правете.
type Stringer interface {
String() string
}
Всеки тип, който имплементира този интерфейс, може да бъде принтиран в Printf например с %s.
Printf просто ще извиква String() и ще вземе стойността.
Всеки обект имплементира празния интерфейс
interface{}С променлива от такъв тип не можем да правим абсолютно нищо. Това може да звучи безполезно, но не е, ако имаме следното...
var value interface{}
value = 20
value = "asd"
str := value.(string)
На последния ред или ще се паникьосаме, или в str ще имаме стойността на value, ако тя наистина е била от тип string.
var value interface{}
switch str := value.(type) {
case string:
return str
case Stringer:
return str.String()Начин да се държим по различен начин въз основа на типа на нещо.