PipeWriter and PipeReader each have a CloseWithError method, which can be used to signal an error in either direction. You could write:

go func() {
pw.CloseWithError(json.NewEncoder(pw).Encode(&v))
}()

This will pass any error from encoding to pw, which will tell the paired PipeReader that the error occurred. If that error is nil, it will just return io.EOF as normal.

You may need more complex error handling for your particular use case.