Как сделать буквенный * int64 в Go?

У меня есть тип структуры с полем *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. Изменить: нет, это не так. Извините.

Edit:

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

Ответ 1

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

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

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

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

1) С new()

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

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

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

2) С лителом среза, индексированием и принятием адреса

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

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

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

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

3) С помощью вспомогательной переменной

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

helper := int64(3)
instance3 := SomeType{
    SomeField: &helper,
}

4) С помощью вспомогательной функции

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

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

И используя его:

instance4 := SomeType{
    SomeField: create(4),
}

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

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

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

instance5 := SomeType{
    SomeField: func(i int64) *int64 { return &i }(5),
}

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

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

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

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

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

type intwrapper struct {
    x int64
}

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

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

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

&(&intwrapper{6}).x

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

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

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

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

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

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

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

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

Ответ 2

Можете ли вы использовать math/big?

package main

import "fmt"
import "math/big"

type AStruct struct{
    ALong *big.Int
}

func main() {
    t := AStruct{ALong : big.NewInt(10)}
    fmt.Printf("t: %v",t)

}