Как получить указатель возвращаемого значения из вызова функции?
Мне просто нужен указатель на time.Time, поэтому код ниже кажется недействительным:
./c.go: 5: не может принимать адрес времени. Теперь()
Я просто удивляюсь, почему? Есть ли способ сделать это, кроме как выполнить назначение переменной сначала и взять указатель на переменную?
package main
import "time"
func main() {
_ = &time.Now()
}
Ответы
Ответ 1
Вероятно, неудовлетворительный ответ: "вы не можете этого сделать, потому что спецификация говорит так". Спектр говорит, что для использования &
для чего-то это должно быть addressable или составной литерал, и чтобы быть адресуемым, оно должно быть "переменная, указатель указателя или операция индексации среза или полевой селектор адресного управляющего операнда или операция индексирования массива адресного массива". Функциональные вызовы и вызовы методов, безусловно, не входят в список.
Практически говоря, это, вероятно, потому, что возвращаемое значение функции может не иметь полезного адреса; он может быть в регистре (в этом случае он определенно не адресуется) или в стеке (в этом случае он имеет адрес, но тот, который не будет действителен, если он поместит указатель, который выходит из текущей области. адресности, Go должен был бы сделать в значительной степени точный эквивалент присвоения ему переменной. Но Go - это тип языка, который показывает, что если он собирается распределить память для переменной, это будет потому, что вы сказали, а не потому, что компилятор волшебно решил, поэтому он не делает результат функции адресуемой.
Или я мог бы передумать, и они просто не хотели иметь специальный случай для функций, которые возвращают одно значение по сравнению с функциями, которые возвращают несколько:)
Ответ 2
Вы не можете напрямую получить адрес вызова функции (или, точнее, возвращаемого значения (ей) функции), как описано в hobbs.
Есть и другой путь, но он безобразен
p := &[]time.Time{time.Now()}[0]
fmt.Printf("%T %p\n%v", p, p, *p)
Выход (Go Playground):
*time.Time 0x10438180
2009-11-10 23:00:00 +0000 UTC
Здесь происходит создание struct
с литералом, содержащим один элемент (возвращаемое значение time.Now()
), фрагмент индексируется (0- й элемент) и берется адрес 0- го элемента.
Так что лучше просто использовать локальную переменную:
t := time.Now()
p := &t
Или вспомогательная функция:
func ptr(t time.Time) *time.Time {
return &t
}
p := ptr(time.Now())
Который также может быть однострочной анонимной функцией:
p := func() *time.Time { t := time.Now(); return &t }()
Или как альтернатива:
p := func(t time.Time) *time.Time { return &t }(time.Now())
Еще больше альтернатив см.:
Как мне сделать литерал * int64 в Go?
Также см. Связанный вопрос: Как я могу сохранить ссылку на результат операции в Go?