User Tools

Site Tools


Q 01

//Q: будут ли изменены элементы в arr?
 
package main
 
func main() {
	arr := [5]int{1, 2, 3, 4, 5}
	arr2 := arr[:]
	arr2[0] = 2
}

A 01

//А: да, так как 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 02

//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 02

//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 03

//Q: будет ли работать данная программа?
 
package main
 
import "fmt"
 
func main() {
	var m map[string]string
	m["name"] = "Vasya"
	fmt.Println(m)
 
}

A 03

// Нет ининициализации объекта и его памяти
//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 04

//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 04

//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 05

//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 05

//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 06

//Q: что будет выведено на экран?
 
package main
 
import "fmt"
 
func main() {
	str := "Привет, мир!"
	if len(str) == 12 {
		fmt.Println("The string length is 12!")
	} else {
		fmt.Println("Nothing")
	}
}

A 06

//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 07

//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 07

//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 08

//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
}

A 08

//А: [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
}

Q 09

Пропускаем

//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)
}

A 09

//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 10

//Q: что будет выведено на экран?
 
package main
 
import "fmt"
 
func main() {
	var y int
	for y := 0; y <= 10; y++ {
		y += 1
	}
	fmt.Println(y)
}

A 10

// y как локальная переменная
//A: 0
//Так как y в цикле является локальной переменной цикла и не оказывает влияния на глобальную переменную
 
package main
 
import "fmt"
 
func main() {
	var y int
	for y := 0; y <= 10; y++ {
		y += 1
	}
	fmt.Println(y)
}

Q 11

Пропускаем

 
// 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")
	}
}

A 11

// 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 12

//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
}

A 12

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
}