//Q: будут ли изменены элементы в arr? package main func main() { arr := [5]int{1, 2, 3, 4, 5} arr2 := arr[:] arr2[0] = 2 }
//А: да, так как arr2 - слайс, который ссылается на массив arr. package main import "fmt" func main() { arr := [5]int{1, 2, 3, 4, 5} arr2 := arr[:] arr2[0] = 2 fmt.Println(arr, arr2) }
//Q: будут ли изменены элементы в arr? package main func main() { arr := [5]int{1, 2, 3, 4, 5} arr2 := arr[1:2] arr3 := append(arr2, 4) arr3[0] = 1 }
//A: да, т.к. arr2 будет иметь ссылку на arr1, иметь len = 1, cap = 9. При использовании append, ссылка не меняется, //если добавленные элементы не превышают возможное cap // package main import "fmt" func main() { arr := [5]int{1, 2, 3, 4, 5} arr2 := arr[1:2] arr3 := append(arr2, 4) arr3[0] = 1 fmt.Println(arr) }
//Q: будет ли работать данная программа? package main import "fmt" func main() { var m map[string]string m["name"] = "Vasya" fmt.Println(m) }
// Нет ининициализации объекта и его памяти //A: программа работать не будет, т.к. при таком объявлении map, переменная ссылается на пустую область памяти. //хорошо, если кандидат ответит почему не работает //лучше, если предложит как поправить package main import "fmt" func main() { /* var m map[string]string m["name"] = "Vasya" fmt.Println(m) */ //еще один не рабочий вариант /* q := new(map[string]string) (*q)["name"] = "Vasya" fmt.Println(*q) */ //1-ый вариант решения m := map[string]string{} m["name"] = "Vasya" fmt.Println(m) //2-ой вариант решения n := map[string]string{ "name": "Vasya", } fmt.Println(n) //3-ой вариант решения (предпочтительный) p := make(map[string]string) p["name"] = "Vasya" fmt.Println(p) }
//Q: что в этой программе не так? package main import "fmt" type MyStruct struct { Name string } func (m MyStruct) ChangeName(newName string) { m.Name = newName } func main() { var m MyStruct m.Name = "Vasya" m.ChangeName("Oleg") fmt.Printf("%+v", m) }
//A: ресивер метода структуры должен быть ссылкой, чтобы происходило изменение объекта package main import "fmt" type MyStruct struct { Name string } func (m *MyStruct) ChangeName(newName string) { m.Name = newName } func main() { var m MyStruct m.Name = "Vasya" m.ChangeName("Oleg") fmt.Printf("%+v", m) }
//Q: как обратиться к полям вложенной структуры, к полю Enable? package main import "fmt" type ExtAddress struct { Address string Port int Enable bool } type Config struct { Address string Port int ExtAddress } func main() { config := Config{ Address: "10.0.0.11", Port: 1234, ExtAddress: ExtAddress{ Address: "172.123.11.12", Port: 3333, Enable: false, }, } fmt.Printf("%+v", config) }
//A: к полям вложенным структуры, если они совпадают с полями внешней структуры можно обратиться, //задав явно имя вложенной структуры //если поля не совпадают по имени - то можно обратиться к ним напрямую package main import "fmt" type ExtAddress struct { Address string Port int Enable bool } type Config struct { Address string Port int ExtAddress } func main() { config := Config{ Address: "10.0.0.11", Port: 1234, ExtAddress: ExtAddress{ Address: "172.123.11.12", Port: 3333, Enable: false, }, } //изменить поле Enable во вложенной структуре config.Enable = true //изменит поле Address во внешней структуре config.Address = "10.0.0.11" //изменит поле Address во внутренней структуре config.ExtAddress.Address = "123.3.3.12" fmt.Printf("%+v", config) }
//Q: что будет выведено на экран? package main import "fmt" func main() { str := "Привет, мир!" if len(str) == 12 { fmt.Println("The string length is 12!") } else { fmt.Println("Nothing") } }
//Q: Nothing. Так как строчки в go имеют юникод формат, то есть, символы могут занимать и по несколько байт. //В то время, как len() возвращает кол-во байт, которые занимает строка. package main import ( "fmt" "unicode/utf8" ) func main() { str := "Привет, мир!" if len(str) == 12 { fmt.Println("The string length is 12!") } else { fmt.Println("Nothing") } //посчитать кол-во символов можно так sum := 0 for range str { sum += 1 } fmt.Println(sum) //или так sum = utf8.RuneCountInString(str) fmt.Println(sum) }
//Q: как получить name компании? package main import "fmt" func main() { myMap := map[string]map[string]string{ "company": { "name": "Digital Energy", }, } fmt.Println(getName(myMap)) } func getName(i interface{}) string { // ??? }
//A: для преобразования interface{} в любой другой тип, необходимо воспользоваться преобразованием типов интерфейса. package main import "fmt" func main() { myMap := map[string]map[string]string{ "company": { "name": "Digital Energy", }, } fmt.Println(getName(myMap)) } func getName(i interface{}) string { m := i.(map[string]map[string]string) return m["company"]["name"] }
//Q: что будет выведено на экран? package main import "fmt" func main() { fmt.Println(do([]int{1, 2, 3})) } func do(n []int) []int { defer func() { n[2] = 2 }() n[0] = 2 return n }
//А: [2,2,2] //Так как slice - ссылочный тип и ф-ия продолжает ссылаться на него после выполнения return, в следствии чего, //все изменения отобразяться и на выводимом slice package main import "fmt" func main() { fmt.Println(do([]int{1, 2, 3})) } func do(n []int) []int { //способ пофиксить - скопировать slice в другой и работать с новым m := make([]int, len(n)) copy(m, n) defer func() { m[2] = 2 }() n[0] = 2 return n }
Пропускаем
//Q0: что здесь происходит? //Q1: что будет, если раскомментировать строку 26 //Q2: что будет, если раскомментировать строку 17 //Q3: что будет, если раскомментировать строку 17 и 26 //Q4: что будет, если раскомментировать строку 27 //Q5: что будет, если раскомментировать строку 17 и 27 //Q6: что можно сделать, чтобы в канал можно было сделать несколько записей? package main func main() { quit := make(chan bool) go func() { for { select { case <-quit: //close(quit) return default: // … } } }() // … quit <- true //quit <- true //fmt.Println(<-quit) }
//Q0: продемонстрирована работа небуффиризоированного канала и горутины, которая считывает запись в канал //Q1: произойдет попытка записи в канал, однако, горутина, работающая с ним будет завершена, что приведет к дедлоку //Q2: программа завершится корректно, канал будет закрыт, горутина остановлена //Q3: произойдет попытка записи в закрытый канал, т.к. он закроется после чтения одной записи //Q4: произойдет повторное чтение из канала, т.к. горутина будет остановлена операцией return - возникнет ошибка - deadlock //Q5: произойдет повторное чтение из канала, горутина будет остановлена, однако, канал так же будет зарыть, но считать из него информацию можно! //будет выведено - false //Q6: package main func main() { quit := make(chan bool) go func() { for { select { case <-quit: //close(quit) return default: // … } } }() // … quit <- true //quit <- true //fmt.Println(<-quit) }
//Q: что будет выведено на экран? package main import "fmt" func main() { var y int for y := 0; y <= 10; y++ { y += 1 } fmt.Println(y) }
// y как локальная переменная //A: 0 //Так как y в цикле является локальной переменной цикла и не оказывает влияния на глобальную переменную package main import "fmt" func main() { var y int for y := 0; y <= 10; y++ { y += 1 } fmt.Println(y) }
Пропускаем
// Q0: скомпилируется ли код? // Q1: что здесь происходит? // Q2: что будет, если заменить const на var в 17 строке? package main import ( "fmt" "reflect" "unsafe" ) type Foo struct { Bar string Baz int Qux bool } const FooSize = unsafe.Sizeof(Foo{}) func main() { foo := Foo{"123", 999, true} fooBytes := *(*[FooSize]byte)(unsafe.Pointer(&foo)) fmt.Println(fooBytes) foo2 := Foo{"123", 999, true} fooBytes2 := *(*[FooSize]byte)(unsafe.Pointer(&foo2)) fmt.Println(fooBytes2) if foo == foo2 { fmt.Println("struct equal") } if fooBytes == fooBytes2 { fmt.Println("[]bytes equal") } if reflect.DeepEqual(foo, foo2) { fmt.Println("DeepEqual equal") } }
// A0: да. // A1: берем ансейф поинтер от структуры foo, кастомим к слайсу байт, и выводим // A2: компиляция вернет ошибку? // invalid array length FooSize package main import ( "fmt" "unsafe" ) func main() { foo := Foo{"123", 999, true} fooBytes := *(*[FooSize]byte)(unsafe.Pointer(&foo)) fmt.Println(fooBytes) }
//Q: что будет выведено на экран? package main import "fmt" type MyErr struct{} func (m MyErr) Error() string { return "my err string" } func main() { fmt.Println(returnError() == nil) fmt.Println(returnErrorPtr() == nil) fmt.Println(returnCustomError() == nil) fmt.Println(returnCustomErrorPtr() == nil) fmt.Println(returnMyError() == nil) } func returnError() error { var err error return err } func returnErrorPtr() *error { var err *error return err } func returnCustomError() error { var customErr MyErr return customErr } func returnCustomErrorPtr() error { var customErr *MyErr return customErr } func returnMyError() *MyErr { return nil }
package main import "fmt" func main() { fmt.Println(returnError() == nil) //true fmt.Println(returnErrorPtr() == nil) //true fmt.Println(returnCustomError() == nil) //false fmt.Println(returnCustomErrorPtr() == nil) //false fmt.Println(returnMyError() == nil) //true }