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


у меня есть тип struct с

2 53

2 ответа:

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

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

для рассуждения, почему это не допускается, см. вопрос: найти адрес константы в 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),
}

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

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

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

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

это означает, что взятие адреса составного литерала, например литерала структуры, в порядке. Если мы это сделаем, у нас будет выделенное значение структуры и указатель получается к нему. Но если это так, то нам станет доступно еще одно требование: "селектор полей адресуемого структурного операнда". Поэтому, если литерал структуры содержит поле типа 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,
}

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

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

 type myStr struct {
        url *int64
    }

    func main() {

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