在写入但不从golang中的存储位置读取时读取SIGSEGV

I was under the impression that using the unsafe package allows you to read/write arbitrary data. I'm trying to change the value the interface{} points to without changing the pointer itself.

Assuming that interface{} is implemented as

type _interface struct {
    type_info *typ
    value unsafe.Pointer
}

setting fails with a SIGSEGV, although reading is successful.

func data(i interface{}) unsafe.Pointer {
    return unsafe.Pointer((*((*[2]uintptr)(unsafe.Pointer(&i))))[1])
}

func main() {
    var i interface{}
    i = 2
    fmt.Printf("%v, %v
", (*int)(data(i)), *(*int)(data(i)))
    *((*int)(data(i))) = 3
}

Am I doing something wrong, or is this not possible in golang?

Hm... Here's how I understand your second code example currently, in case I've made an error (if you notice anything amiss in what I'm describing, my answer is probably irredeemably wrong and you should ignore the rest of what I have to say).

  1. Allocate memory for interface i in main.
  2. Set the value of i to an integer type with the value 2.
  3. Allocate memory for interface i in data.
  4. Copy the value of main's i to data's i; that is, set the value of the new interface to an integer type with the value 2.
  5. Cast the address of the new variable into a pointer to length-2 array of uintptr (with unsafe.Pointer serving as the intermediary that forces the compiler to accept this cast).
  6. Cast the second element of the array (whose value is the address of the value-part of i in data) back into an unsafe.Pointer and return it.

I've made an attempt at doing the same thing in more steps, but unfortunately I encountered all the same problems: the program recognizes that I have a non-nil pointer and it's able to dereference the pointer for reading, but using the same pointer for writing produces a runtime error.

It's step 6 that go vet complains about, and I think it's because, according to the package docs,

A uintptr is an integer, not a reference. Converting a Pointer to a uintptr creates an integer value with no pointer semantics. Even if a uintptr holds the address of some object, the garbage collector will not update that uintptr's value if the object moves, nor will that uintptr keep the object from being reclaimed.

More to the point, from what I can tell (though I'll admit I'm having trouble digging up explicit confirmation without scanning the compiler and runtime source), the runtime doesn't appear to track the value-part of an interface{} type as a discrete pointer with its own reference count; you can, of course, trample over both the interface{}'s words by writing another interface value into the whole thing, but that doesn't appear to be what you wanted to do at all (write to the memory address of a pointer that is inside an interface type, all without moving the pointer).

What's interesting is that we seem to be able to approximate this behavior by just defining our own structured type that isn't given special treatment by the compiler (interfaces are clearly somewhat special, with type-assertion syntax and all). That is, we can use unsafe.Pointer to maintain a reference that points to a particular point in memory, and no matter what we cast it to, the memory address never moves even if the value changes (and the value can be reinterpreted by casting it to something else). The part that surprises me a bit is that, at least in my own example, and at least within the Playground environment, the value that is pointed to does not appear to have a fixed size; we can establish an address to write to once, and repeated writes to that address succeed even with huge (or tiny) amounts of data.

Of course, with at least this implementation, we lose a bunch of the other nice-to-have things we associate with interface types, especially non-empty interface types (i.e. with methods). So, there's no way to use this to (for example) make a super-sneaky "generic" type. It seems that an interface is its own value, and part of that value's definition is an address in memory, but it's not entirely the same thing as a pointer.