Моя функция возвращает структуру; почему присваивание полю этого значения результата запрещено компилятором? - PullRequest
0 голосов
/ 16 января 2020

В golang, если я возвращаю тип структуры в функцию, я получаю ошибку компиляции, я должен использовать указатель структуры в качестве возвращаемого типа, чтобы получить доступ к члену напрямую через вызов функции. Это почему? Разве foo () не возвращает временную переменную типа Employee?

package main


type Employee struct {
ID int
Name string
Address string
Position string
Salary int
ManagerID int
}
var dilbert Employee


func foo() Employee {
    employee := Employee{}
    return employee
}

func bar() *Employee {
    employee := Employee{}
    return &employee
}

func main() {
    dilbert.Salary = 1
    var b = foo()
    b.Salary = 1

    bar().Salary = 1    // this is good
    foo().Salary = 1    // this line has the compilation error cannot assign to foo().Salary
}

Ответы [ 3 ]

1 голос
/ 16 января 2020

foo () возвращает «значение» типа структуры, и мы не можем ничего присвоить значению. В то время как bar () возвращает указатель на переменную. Мы можем использовать этот указатель, чтобы присвоить другое значение этой переменной

Эта ошибка по существу не связана со структурой, а связана с присвоением значения значению. Рассмотрим следующий пример:


func retint() int{
    var a int=5
    return a
}

func retintp() *int{
    var a int=5
    return &a
}
func main(){
    print("hello")
    *retintp()=10   // this is valid as we can store 10 to address pointed by a
    retint()=10     // this gives error. as we can not assign 10 to 5

}

Здесь retint () возвращает значение (5). мы не можем ничего присвоить 5, но retintp () возвращает адрес переменной a. Мы можем использовать этот адрес, чтобы присвоить ему значение

1 голос
/ 16 января 2020

В Go, переменная является адресуемым значением, то есть значением, которое вы можете получить по адресу. Вы можете назначить только переменную, но не неадресуемое значение.

bar().Salary = 1 допустимо, поскольку

  1. bar().Salary на самом деле является syntacti c сахар для (*bar()).Salary;
  2. *bar() является (структурной) переменной, поскольку вы можете получить ее адрес;
  3. поля (например, Salary) структурной переменной сами являются переменными.

Напротив, foo().Salary = 1 недопустимо, потому что foo().Salary является значением, но это , а не переменная; нет способа получить адрес foo(). Это объясняет, почему это утверждение отклонено компилятором. Обратите внимание, что введение промежуточной переменной решает вашу проблему:

// type and function declarations omitted

func main() {
    f := foo()
    f.Salary = 1 // compiles fine
}
0 голосов
/ 16 января 2020
bar().Salary = 1 

Возвращает указатель, и мы записываем объект, на который указывает указатель

foo().Salary = 1

foo () возвращает временный объект, и поскольку мы его нигде не храним, временный объект будет потерян, если не назначен переменной. Следовательно go компилятор жалуется

Следующее будет работать

f = foo()
f.Salary = 1
...