Go технически не имеет приведений , а скорее преобразований . Синтаксис для явного преобразования: T(x)
, где T
- некоторый тип, а x
- некоторое значение, которое может быть преобразовано в этот тип. Подробнее см. Преобразования в спецификации Go .
Как видно из объявления функции:
func (lt *LeaveType) UnmarshalJSON(b []byte) error {
lt
сам по себе имеет тип указатель на LeaveType
и UnmarshalJSON
является функцией приемника для типа *LeaveType
. Пакет encoding/json
будет вызывать такую функцию для декодирования ввода JSON, когда переменная, которую пакет хочет установить, имеет тип LeaveType
(или *LeaveType
- в этом случае пакет сам создаст переменную LeaveType
).
Как говорится в комментарии в коде, автор кода теперь хотел бы, чтобы код encoding/json
отменял маршализацию JSON , как если бы не было функцией UnmarshalJSON
. Но - это функция UnmarshalJSON
, поэтому, если мы просто вызовем код encoding/json
без небольшой хитрости, encoding/json
просто вызовет эту функцию снова, что приведет к бесконечной рекурсии.
Определяя новый тип LT
, содержимое которого точно совпадает с существующим типом LeaveType
, мы получаем новый тип, который не не имеет получателя функция. Вызов encoding/json
для экземпляра этого типа (или указателя на этот тип) не вызовет приемник *LeaveType
, потому что LT
- это другой тип, даже если содержимое точно соответствует.
Мы могли бы сделать это:
func (lt *LeaveType) UnmarshalJSON(b []byte) error {
type LT LeaveType
var r LT
err := json.Unmarshal(b, &r)
if err != nil {
panic(err)
}
// ...
}
Это заполнит r
, который имеет тот же размер и форму, что и любая переменная LeaveType
, Тогда мы могли бы использовать заполненный r
, чтобы установить *lt
:
*lt = LeaveType(r) // an ordinary conversion
, после чего мы могли бы продолжать идти как прежде, используя *lt
в качестве значения. Но это означает, что UnmarshalJSON
пришлось установить временную переменную r
, которую мы затем должны были скопировать в конечный пункт назначения. Почему бы вместо этого не настроить что-то так, чтобы UnmarshalJSON
заполняло целевую переменную, но используя выбранный нами тип?
Вот каков здесь синтаксис для . Это не самая короткая версия 1076 *: как отметил Cerise Limón, существует более короткий способ его написания (и это более короткое написание обычно предпочтительнее). Первый набор скобок в (*LT)(lt)
требуется для привязки *
- указатель к части - к LT
, так как *LT(lt)
имеет неправильную привязку: это означает то же самое, что и *(LT(lt))
это не то, что мы хотим.