pointers - variable - golang*int




Как мне сделать литерал*int64 в Go? (2)

Использование функции, возвращающей адрес переменной int64, решит проблему.

В приведенном ниже коде мы используем функцию f, которая принимает целое число и возвращает значение указателя, которое содержит адрес целого числа. Используя этот метод, мы можем легко решить вышеуказанную проблему.

 type myStr struct {
        url *int64
    }

    func main() {

        f := func(s int64) *int64 {
            return &s
        }
        myStr{
            url: f(12345),
        }
    }

У меня есть тип структуры с полем *int64 .

type SomeType struct {
    SomeField *int64
}

В какой-то момент в моем коде я хочу объявить литерал этого (скажем, когда я знаю, что указанное значение должно быть 0 или указывает на 0, вы понимаете, о чем я)

instance := SomeType{
    SomeField: &0,
}

... кроме того, что это не работает

./main.go:xx: cannot use &0 (type *int) as type *int64 in field value

Так что я пытаюсь это

instance := SomeType{
    SomeField: &int64(0),
}

... но это тоже не работает

./main.go:xx: cannot take the address of int64(0)

Как мне это сделать? Единственное решение, которое я могу придумать, это использование переменной-заполнителя.

var placeholder int64
placeholder = 0

instance := SomeType{
    SomeField: &placeholder,
}

Примечание: синтаксис &0 работает нормально, когда это * int вместо *int64 . Редактировать: нет, это не так. Извини за это.

Редактировать:

Очевидно, в моем вопросе было слишком много неясностей. Я ищу способ буквально заявить *int64 . Это может быть использовано внутри конструктора или для определения литеральных значений структуры, или даже в качестве аргументов для других функций. Но вспомогательные функции или использование другого типа не являются решениями, которые я ищу.


Спецификация языка Go ( операторы адреса ) не позволяет получить адрес числовой константы (не типизированной и не типизированной константы).

Операнд должен быть адресуемым , т. Е. Либо переменной, либо косвенным указателем, либо операцией индексации слайса; или селектор поля адресуемого структурного операнда; или операция индексации массива адресуемого массива. В качестве исключения из требования адресуемости, x [в выражении &x ] также может быть (возможно заключенным в скобки) составным литералом .

Чтобы понять, почему это не разрешено, см. Связанный вопрос: Найти адрес постоянной в go . Аналогичный вопрос (аналогично не разрешается брать его адрес): как я могу сохранить ссылку на результат операции в Go?

Ваши варианты (попробуйте все на Go Playground ):

1) С new()

Вы можете просто использовать встроенную функцию new() чтобы выделить новый нулевой int64 и получить его адрес:

instance := SomeType{
    SomeField: new(int64),
}

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

2) с вспомогательной переменной

Простейшим и рекомендуемым для ненулевых элементов является использование вспомогательной переменной, адрес которой может быть получен:

helper := int64(2)
instance2 := SomeType{
    SomeField: &helper,
}

3) с функцией помощника

Или, если вам нужно это много раз, вы можете создать вспомогательную функцию, которая выделяет и возвращает *int64 :

func create(x int64) *int64 {
    return &x
}

И используя это:

instance3 := SomeType{
    SomeField: create(3),
}

Обратите внимание, что мы на самом деле ничего не выделяли, компилятор Go сделал это, когда мы вернули адрес аргумента функции. Компилятор Go выполняет escape-анализ и размещает локальные переменные в куче (вместо стека), если они могут экранировать функцию. Подробнее см. Безопасно ли возвращать фрагмент локального массива в функции Go?

4) с однострочной анонимной функцией

instance4 := SomeType{
    SomeField: func() *int64 { i := int64(4); return &i }(),
}

Или как (более короткая) альтернатива:

instance4 := SomeType{
    SomeField: func(i int64) *int64 { return &i }(4),
}

5) С литералом среза, индексацией и получением адреса

Если вы хотите, чтобы *SomeField от 0 , вам нужно что-то адресуемое.

Вы все еще можете сделать это, но это ужасно

instance5 := SomeType{
    SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5

Здесь происходит срез []int64 с литералом, имеющим один элемент ( 5 ). И это индексируется (0-й элемент), и адрес 0-го элемента берется. В фоновом режиме также будет выделен массив [1]int64 который будет использоваться в качестве [1]int64 массива для среза. Так что здесь много шаблонов.

6) С вспомогательной литералом структуры

Давайте рассмотрим исключение из требований адресуемости:

В качестве исключения из требования адресуемости, x [в выражении &x ] также может быть (возможно заключенным в скобки) составным литералом .

Это означает, что брать адрес составного литерала, например, структурного литерала, можно. Если мы сделаем это, у нас будет выделено значение структуры и получен указатель на него. Но если это так, нам станет доступно другое требование: «селектор поля адресуемого операнда структуры» . Так что, если литерал структуры содержит поле типа int64 , мы также можем взять адрес этого поля!

Давайте посмотрим на эту опцию в действии. Мы будем использовать этот тип структуры оболочки:

type intwrapper struct {
    x int64
}

И теперь мы можем сделать:

instance6 := SomeType{
    SomeField: &(&intwrapper{6}).x,
}

Обратите внимание, что это

&(&intwrapper{6}).x

означает следующее:

& ( (&intwrapper{6}).x )

Но мы можем опустить «внешнюю» круглую скобку, поскольку оператор адреса & применяется к результату выражения селектора .

Также обратите внимание, что в фоновом режиме произойдет следующее (это также допустимый синтаксис):

&(*(&intwrapper{6})).x

7) С помощником анонимной структуры литерала

Принцип тот же, что и в случае №6, но мы также можем использовать анонимный структурный литерал, поэтому определение типа структуры помощника / оболочки не требуется:

instance7 := SomeType{
    SomeField: &(&struct{ x int64 }{7}).x,
}




literals