#go
#Вперед
Вопрос:
Вызов функции
Когда я определяю структуру Lock
и функцию Test
со структурой Lock
в качестве получателя функции
type Lock struct {
}
func (self Lock) Test() {
fmt.Println("Test Func")
}
Я обнаружил, что могу вызвать эту функцию с помощью структурного указателя Lock
lock := amp;Lock{}
lock.Test()
То же самое, если я определяю структуру Lock
и функцию Test
в качестве Lock
указателя в качестве получателя, я могу вызвать эту функцию через Lock
экземпляр struct .
Итак, каким бы получателем ни была сама структура или указатель на структуру, я могу вызвать эту функцию через оба? В чем причина. Насколько я понимаю, struct и указатель struct — это совершенно два разных типа!
Интерфейс
Если определить интерфейс Locker
, подобный этому
type Locker interface {
Test()
}
И определите структуру Lock
и функцию Test
с экземпляром struct в качестве получателя, я не могу назначить переменную указателя Locker
структуры переменной интерфейса.
Напротив, если a определяет структуру Lock
и функцию Test
с указателем структуры в качестве получателя, присвоение переменной экземпляра структуры переменной Locker
интерфейса может работать!
Я так смущен дизайном языка. Кто-нибудь может дать мне несколько советов?
Комментарии:
1. Вы ищете правила для селекторов
2. И взгляните на спецификацию языка в целом, особенно на разделы набора методов. И, конечно же: совершите экскурсию по Go еще раз.
Ответ №1:
Обычно Go делает что-то для вас под капотом, и это, как правило, один из таких случаев.
Когда вы определяете функцию со структурой в качестве получателя и передаете ей указатель на структуру, Go выполняет преобразование за вас: он передает копию структуры, на которую указывает.
Когда вы определяете функцию с указателем в качестве получателя и передаете ей структуру, Go создает указатель на эту структуру.
Однако при определении интерфейса вы работаете с типами: Locker
интерфейс определяет тип, который реализует функцию Test()
.
И с интерфейсами Go вам не поможет: если ваш тип не реализует метод, то он не реализует интерфейс. Здесь нет скрытого преобразования.
Обычно лучше четко представлять, что вы хотите и как вы этого хотите, и, таким образом, предотвращать выполнение Go этих странных преобразований.
Комментарии:
1. Не совсем точно. Go все еще выполняет небольшое преобразование для интерфейсов. Правило состоит в том, что если вы передаете указатель на тип в интерфейс, методы указателя и значения для этого типа могут выполнять интерфейс. Если вы передаете сам тип, только методы значений для этого типа могут выполнять интерфейс. Пример: play.golang.org/p/rUIeMBnXTY
2. Спасибо за ваш ответ! Это действительно помогает мне разобраться в этом.