Идите структурировать литералы, почему этот адрес адресуемый?
Я читаю книгу "Язык программирования Go". Это очень хорошо для нас (скорее) опытных программистов и объясняет различия между пересечениями других языков - но я нашел случай, который я не до конца понимаю.
Я знаю C++ достаточно хорошо, и я понимаю, что Go называет (что бы в C++ называлось) rvalues /xvalues "неадресуемые". Только "переменные" [слова GOPL] являются адресуемыми.
Хорошо, достаточно справедливо; это имеет смысл.
И поэтому, например, это незаконно (согласно стр. 159 в первом печатном издании)
Point{1, 2}.ScaleBy(2) // compile error: can't take address of Point literal
так как (*Point).ScaleBy
занимает *Point
в качестве аргумента получателя и Point
литерал не адресуемый.
(Если вы не читали книгу, Point
это структура с полями X, Y float64
,
Однако на странице 162 мы имеем
type ColoredPoint struct {
*Point
Color color.RGBA
}
p := ColoredPoint(&Point{1, 1}, red)
// ...more code ...
который, по-видимому, действителен и будет компилироваться.
Вопрос:
Почему Point
буквальный во втором случае адресуемый?
Это особый случай для удобства, или я что-то упускаю из общей картины?
3 ответа
&T{}
обозначения поясняются в разделе 4.4.1, Литералы структуры, на странице 103:
Поскольку структуры так часто обрабатываются с помощью указателей, можно использовать эту сокращенную запись для создания и инициализации переменной структуры и получения ее адреса:
pp := &Point{1, 2}
Это в точности эквивалентно
pp := new(Point) *pp = Point{1, 2}
но
&Point{1, 2}
может использоваться непосредственно в выражении, таком как вызов функции.
Рад, что в противном случае вы наслаждаетесь книгой.
Это особый случай для удобства. Спецификация упоминает здесь исключение.
В качестве исключения из требования адресуемости, x также может быть (возможно заключенным в скобки) составным литералом.
Добавим немного больше деталей к ответу Mellow Marmot:
Вызов встроенной функции
new
или взятие адреса составного литерала выделяет память для переменной во время выполнения. На такую анонимную переменную ссылаются через (возможно, неявную) указатель косвенности.
Point{1, 1}
является составным литералом, взяв его адрес создаст анонимную переменную под капотом, а результатом выражения будет адрес этой анонимной переменной.
Итак, как вы можете видеть технически, это переменная, к которой обращаются, поэтому она не нарушает это:
Только "переменные" [слова GOPL] являются адресуемыми.
Также ознакомьтесь с этим ответом, чтобы узнать, какие еще "полезности" или приемы вы можете сделать: как сделать литерал *int64 в Go?