在仅标签不同的相同结构类型之间进行不安全的转换

Consider two types identical in structure but differing in their tags:

type Foo struct {
  Id int64 `json:"-"`
}

type Bar struct {
  Id int64 `json:"id"`
}

Unfortunately Go's idiom forbids casting between two types when their tags differ and for good reason. However I still need to be able to control the data that is serialised to JSON and don't want to use interface{} types.

My question is, how safe is it to use golang's unsafe.Pointer to perform casts between two types which are identical in structure (but not tags)? Something like:

rf := &Foo{1}
rb := (*Bar)(unsafe.Pointer(rf))

Is there any chance at all of a panic ensuing maybe because internally the data in each of the two types is held slightly differently due to the tags differing or is the information about tags held separate from the actual type data and data in each of the types is structurally identical?

EDIT

For clarification I should mention that although the example provided above employs single-field structs, the question is really about struct types containing multiple fields.

Strictly speaking, this isn't safe. The reason is that the relevant section of the spec doesn't give any guidelines for memory layout for structs. It doesn't guarantee in-memory field ordering, packing, or alignment. In theory, a compiler could, based on optimization info, decide two seemingly identical structs are to be represented differently based on their usage. This could even be a Heisenbug where the offending optimization doesn't happen in go test builds.

Practically speaking, this is unlikely to happen in any real compiler and you can probably do it safely. This is especially true of one field structs like the one you provided. You should probably ensure through profiling that copying is insufficient before you go doing this though.

Unfortunately Go's idiom forbids casting between two types when their tags differ and for good reason

The release notes for Go 1.8 (currently in beta) seems to indicate this restriction is now lifted:

Changes to the language

When explicitly converting a value from one struct type to another, as of Go 1.8 the tags are ignored.
Thus two structs that differ only in their tags may be converted from one to the other:

func example() {
    type T1 struct {
        X int `json:"foo"`
    }
    type T2 struct {
        X int `json:"bar"`
    }
    var v1 T1
    var v2 T2
    v1 = T1(v2) // now legal
}