Задачи на указатель
1) Что выведет данная программа и почему?
В данной программе на Go будет выведено:
Это происходит потому, что в функции changeName
, когда мы передаем указатель на структуру Person
, мы создаем новый указатель на новый экземпляр Person
с именем "Alice", но это изменение не отражается на исходном указателе person
в функции main
. Поэтому значение имени остается "Bob" как и было изначально.
как исправить эту программу, чтобы изменение имени происходило?
Чтобы изменение имени происходило, нужно изменить функцию changeName
так, чтобы она изменяла значение, на которое указывает указатель person
, а не создавала новый указатель. Это можно сделать, не присваивая новому указателю, а изменяя значение, на которое указывает person
. Вот пример исправленной программы:
В этом примере, когда мы вызываем changeName(person)
, мы изменяем значение поля Name
структуры Person
, на которую указывает person
. Поэтому, когда мы выводим person.Name
после вызова changeName
, мы увидим "Alice", а не "Bob".
2) Что выведет на экран данная программа?
В данной программе будет выведено значение 0
, а не 1
, как могло бы показаться на первый взгляд. Давайте разберем, почему это происходит:
В программе определен новый тип
Count
какint
.Далее определен метод
Increment
для типаCount
, который должен увеличивать значение на 1.В функции
main
создается переменнаяcount
типаCount
.Затем вызывается метод
Increment
для переменнойcount
. Однако, в данном случае методIncrement
принимает значениеCount
по значению, а не по указателю, поэтому изменения не отражаются на исходной переменной.При вызове
count.Increment()
, значениеcount
копируется в методIncrement
, увеличивается, но изменения не сохраняются в исходной переменнойcount
.Поэтому при выводе переменной
count
на экран с помощьюfmt.Print(count)
, будет выведено значение0
.
Итак, программа выведет на экран значение 0
, так как метод Increment
увеличивает копию значения переменной count
, но не изменяет саму переменную.
Для исправления данной программы, чтобы она выводила значение 1
вместо 0
, необходимо изменить метод Increment
так, чтобы он принимал указатель на Count
вместо значения Count
. Это позволит изменять исходное значение переменной count
.
Вот исправленная версия программы:
Изменения:
Метод
Increment
теперь принимает указатель наCount
вместо значенияCount
:func (c *Count) Increment()
.Внутри метода
Increment
мы используем разыменование указателя*c++
для увеличения значения, на которое указываетc
.В
main
функции мы по-прежнему вызываемcount.Increment()
, но теперь это корректно изменяет значение переменнойcount
.При выводе
fmt.Print(count)
будет напечатано1
, так как значениеcount
было увеличено на 1.
Таким образом, изменив метод Increment
так, чтобы он принимал указатель на Count
, мы можем корректно изменять значение исходной переменной count
и получать ожидаемый результат.
3) Что выведет данная программа и почему?
Данная программа на Go выведет следующее:
Вот объяснение:
var s *string
:Здесь мы объявляем указатель на строку
s
, который по умолчанию имеет значениеnil
.Поэтому
fmt.Println(s == nil)
выводитtrue
.
var i interface{}
:Здесь мы объявляем переменную
i
типаinterface{}
, которая также по умолчанию имеет значениеnil
.Поэтому
fmt.Println(i == nil)
выводитtrue
.
i = s
:Здесь мы присваиваем значение
s
(которое равноnil
) переменнойi
типаinterface{}
.Несмотря на то, что
s
равенnil
,i
теперь содержит указатель на строку, который не равенnil
.Поэтому
fmt.Println(i == nil)
выводитfalse
.
Таким образом, программа выводит:
true
- потому чтоs
равенnil
.true
- потому чтоi
по умолчанию равенnil
.false
- потому что после присваиванияs
переменнойi
,i
больше не равенnil
.
Ключевой момент здесь в том, что тип interface{}
может содержать любое значение, в том числе nil
. Поэтому, когда мы присваиваем nil
указатель на строку переменной i
, i
больше не равен nil
.
4) Что выведет данный код и почему?
Этот код демонстрирует интересный случай с нулевыми указателями в Go. Давайте разберем его по частям и объясним, что он выведет и почему.
Объяснение кода
Функция
main
:Вызывает функцию
do
и проверяет, вернула ли она ошибку.Если ошибка не
nil
, выводит "oops", иначе выводит "OK".
Функция
do
:Объявляет переменную
p
типа указателя наMyError
и инициализирует ее значениемnil
.Условие
if false
никогда не выполняется, поэтомуp
остаетсяnil
.Возвращает
p
.
Структура
MyError
:Определяет структуру с полем
msg
типаstring
.Реализует метод
Error
, который возвращает значение поляmsg
.
Что происходит при выполнении
Переменная
p
типа*MyError
инициализируется значениемnil
.Условие
if false
никогда не выполняется, поэтомуp
остаетсяnil
.Функция
do
возвращаетnil
типа*MyError
.
Важный момент
В Go, если переменная типа error
имеет значение nil
, это считается отсутствием ошибки. Однако, если переменная типа *MyError
имеет значение nil
, она все равно может быть приведена к типу error
, и это будет корректное значение типа error
, но содержащее nil
.
Проверка в main
main
В
main
, переменнаяerr
будет иметь значениеnil
типаerror
.Условие
if err != nil
проверяет, является лиerr
nil
.Поскольку
err
действительноnil
, условиеif err != nil
будет ложным.
Вывод
Таким образом, программа выведет:
Заключение
Этот пример показывает, что в Go переменная типа *MyError
, имеющая значение nil
, может быть приведена к типу error
, и это будет корректное значение типа error
, но содержащее nil
. В результате проверка if err != nil
будет ложной, и программа выведет "OK".
Last updated