github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/eface_test.go (about)

     1  package jzon
     2  
     3  import (
     4  	"log"
     5  	"reflect"
     6  	"runtime/debug"
     7  	"testing"
     8  	"unsafe"
     9  
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestEface(t *testing.T) {
    14  	f := func(o interface{}) *eface {
    15  		return (*eface)(unsafe.Pointer(&o))
    16  	}
    17  	a := 1
    18  	b := 2
    19  	ef1 := f(&a)
    20  	ef2 := f(&b)
    21  	require.Equal(t, ef1.rtype, ef2.rtype)
    22  	// require.Equal(t, uintptr(strconv.IntSize/8), uintptr(ef2.data)-uintptr(ef1.data))
    23  	t.Logf("%x %x", ef1.rtype, ef1.data)
    24  	t.Logf("%x %x", ef2.rtype, ef2.data)
    25  
    26  	// with reflect
    27  	r := reflect.TypeOf(&a)
    28  	ef3 := (*eface)(unsafe.Pointer(&r))
    29  	require.Equal(t, ef1.rtype, uintptr(ef3.data))
    30  	require.Equal(t, ef1.rtype, rtypeOfType(r))
    31  
    32  	// pack
    33  	packed := packEFace(rtype(ef3.data), ef1.data)
    34  	t.Logf("%+v", packed)
    35  	v, ok := packed.(*int)
    36  	t.Logf("%+v %+v", v, ok)
    37  	require.True(t, ok)
    38  	require.Equal(t, &a, v)
    39  }
    40  
    41  func TestEface2(t *testing.T) {
    42  	func() {
    43  		i := 1
    44  		var o interface{} = i
    45  		ef := packEFace(rtypeOfType(reflect.TypeOf(i)), unsafe.Pointer(&i))
    46  
    47  		t.Log("o", o)
    48  		t.Log("ef", ef)
    49  		i2 := ef.(int)
    50  		t.Log("i2", i2)
    51  
    52  		i = 2
    53  		t.Log("o", o)
    54  		t.Log("ef", ef)
    55  		t.Log("i2", i2)
    56  	}()
    57  	debug.FreeOSMemory()
    58  }
    59  
    60  type testEFstruct struct {
    61  	a int
    62  }
    63  
    64  func (t testEFstruct) Foo() {
    65  	log.Printf("calling %x", unsafe.Pointer(&t))
    66  	t.a++
    67  }
    68  
    69  func (t testEFstruct) Int() int {
    70  	return t.a
    71  }
    72  
    73  func TestEface3(t *testing.T) {
    74  	var f func(o interface{}, i int)
    75  	f = func(o interface{}, i int) {
    76  		ef := (*eface)(unsafe.Pointer(&o))
    77  		log.Println("->", i, ef.data)
    78  		if i > 0 {
    79  			f(o, i-1)
    80  		}
    81  	}
    82  	f2 := func(o interface{}) {
    83  		v := reflect.ValueOf(o)
    84  		o2 := v.Interface()
    85  		f(o2, 1)
    86  	}
    87  	func() {
    88  		var st testEFstruct
    89  		f(st, 1)
    90  		log.Printf("&st, %p", &st)
    91  		log.Printf("st.a, %d", st.a)
    92  
    93  		f2(st)
    94  
    95  		type ifoo interface {
    96  			Foo()
    97  			Int() int
    98  		}
    99  
   100  		var foo ifoo = st
   101  		log.Println("iface data", (*iface)(unsafe.Pointer(&foo)).data)
   102  		foo.Foo()
   103  		log.Printf("st.a, %d", st.a)
   104  		log.Printf("foo.Int(), %d", foo.Int())
   105  		foo.Foo()
   106  		log.Printf("foo.Int(), %d", foo.Int())
   107  
   108  		ef := packEFace(rtypeOfType(reflect.TypeOf(st)), unsafe.Pointer(&st))
   109  		foo = ef.(ifoo)
   110  		foo.Foo()
   111  		log.Printf("st.a, %d", st.a)
   112  	}()
   113  	debug.FreeOSMemory()
   114  }