Преобразование типов между двумя указателями на структуры

У меня есть struct, который состоит из пользовательского time.Time, определенного для того, чтобы иметь собственный интерфейс MarshalJSON(), следуя предложению этот ответ:

type MyTime time.Time
func (s myTime) MarshalJSON() ([]byte, error) {
    t := time.Time(s)
    return []byte(t.Format(`"20060102T150405Z"`)), nil
}

Я определяю тип MyStruct с полями ThisDate и ThatDate типа *MyTime:

type MyStruct struct {
    ThisDate *MyTime `json:"thisdate,omitempty"`
    ThatDate *MyTime `json:"thatdate,omitempty"`
}

Насколько я понимаю, мне нужно использовать *MyTime, а не MyTime, поэтому тег omitempty будет иметь эффект, когда я буду MarshalJSON переменную этого типа, следуя предложению этот ответ.

Я использую библиотеку с функцией, которая возвращает мне struct с некоторыми полями типа *time.Time:

someVar := Lib.GetVar()

Я попытался определить переменную типа MyStruct следующим образом:

myVar := &MyStruct{
    ThisDate: someVar.ThisDate
    ThatDate: someVar.ThatDate
}

Естественно, это дает мне ошибку компиляции:

cannot use someVar.ThisDate (variable of type *time.Time) as *MyTime value in struct literal ...

Я пробовал приведение типов someVar.ThisDate с */& и без них, но безуспешно. Я думал, что следующее будет работать:

myVar := &MyStruct{
    ThisDate: *MyTime(*someVar.ThisDate)
    ThatDate: *MyTime(*someVar.ThatDate)
}

Но это дает мне другую ошибку компиляции:

invalid operation: cannot indirect MyTime(*someVar.ThisDate) (value of type MyTime) ...

Кажется, мне, вероятно, не хватает базового понимания указателей и разыменований в Go. Тем не менее, я хотел бы избежать поиска конкретного решения моей проблемы, которое сводится к сочетанию необходимости сделать omitempty эффект и кастом MarshalJSON.

(*MyTime)(someVar.ThisDate)someVar.ThisDate уже *time.Time верно? так что вам не нужно * перед ним. Кроме того, при преобразовании в типы указателей, то есть *T, я бы рекомендовал всегда помещать тип указателя в дополнительные круглые скобки, то есть (*T). play.golang.com/p/jH9Q07sizID
mkopriva 25.05.2019 22:03

Это очень полезно, спасибо! Не могли бы вы объяснить этот синтаксис? Я видел его много раз, и я даже не знаю, как его искать, чтобы найти документацию о нем. Возможно, подойдет даже ссылка на нужное место в tour.golang.org.

Doron Behar 25.05.2019 22:45
golang.org/ref/spec#КонверсииЕсли тип начинается с оператора * или <-, или если тип начинается с ключевого слова func и не имеет списка результатов, при необходимости он должен быть заключен в скобки, чтобы избежать двусмысленности.
mkopriva 25.05.2019 22:46

Если вы понимаете концепцию приоритета оператора или порядка оценки, вы можете увидеть, что *T(v) может быть интерпретировано двояко и, следовательно, неоднозначно, поэтому к избежать двусмысленности вы можете пояснить свое намерение, добавив круглые скобки (*T)(v).

mkopriva 25.05.2019 22:54

Это отличное объяснение @mkopriva - именно то, чего мне не хватало. Пожалуйста, не стесняйтесь вставлять эти слова в ответ, который я отмечу как принятый.

Doron Behar 25.05.2019 23:00

В Go вообще нет приведения типов.

Flimzy 26.05.2019 10:56

Пожалуйста, найдите время, чтобы также усвоить то, что сказал Флимзи: в Go нет type_casting_ — то есть принудительной переинтерпретации значения одного типа как значения другого. Вместо этого в Go есть тип конверсии;, который отличается тем, что позволяет преобразовывать значения между совместимыми типами, где совместимость примерно означает «представление значений, которые имеют одинаковые макеты памяти для своих данных».

kostix 27.05.2019 18:48

Спасибо @kostix, я отредактировал заголовок вопроса.

Doron Behar 28.05.2019 08:37
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
0
8
583
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в неоднозначном синтаксисе *T(v) или чего-то еще, что вы там пробовали. спецификация Голанга дает полезные примеры преобразования типов, цитируя:

*Point(p)        // same as *(Point(p))
(*Point)(p)      // p is converted to *Point

Поэтому, поскольку *Point необходимо, следует использовать *T(v).

(*T)(v) для *Point; чтобы получить балл, это *(*T)(v).

Phil P 09.01.2022 10:22

Другие вопросы по теме