dongrao1862 2017-12-15 10:51
浏览 40

使用模板的反射创建的值时出现意外的故障地址

I want to minimic type testData by reflect, but got unexpected fault address

func TestData(t *testing.T) {
    tpl, err := template.New("ok").Parse("{{.Ok}}")
    if err != nil {
        panic(err)
    }
    buf := bytes.NewBuffer(nil)
    myTyp := reflect.StructOf([]reflect.StructField{
        {Name: "MyFace", Type: reflect.TypeOf((*MyFace)(nil)).Elem(), Index: []int{0}, Anonymous: true},
    })
    myVal := reflect.New(myTyp).Elem()
    myVal.Field(0).Set(reflect.ValueOf(MyFace(&testFace{})))
    err = tpl.Execute(buf, myVal.Interface()) // unexpected fault address
    //err = tpl.Execute(buf, &testDat{MyFace: MyFace(&testFace{})}) // works as expected
    if err != nil {
        panic(err)
    }
    fmt.Println(buf.String())
}

type testData struct {
    MyFace
}
type testFace struct {
}

func (testFace) Ok() string {
    return "All right"
}

type MyFace interface {
    Ok() string
}

ERROR

unexpected fault address 0xc4200e83a0
[signal SIGBUS: bus error code=0x2 addr=0xc4200e83a0 pc=0xc4200e83a0]

goroutine 5 [running]:
runtime.throw(0x13728ac, 0x5)
    /usr/local/Cellar/go/1.9.1/libexec/src/runtime/panic.go:605 +0x95 fp=0xc420058fe8 sp=0xc420058fc8 pc=0x102d235
runtime.sigpanic()
    /usr/local/Cellar/go/1.9.1/libexec/src/runtime/signal_unix.go:364 +0x29d fp=0xc420059038 sp=0xc420058fe8 pc=0x1043c2d
runtime.call32(0xc42007f260, 0xc42000e0a8, 0xc4200e8560, 0x800000018)
    /usr/local/Cellar/go/1.9.1/libexec/src/runtime/asm_amd64.s:509 +0x3b fp=0xc420059068 sp=0xc420059038 pc=0x105a51b
reflect.Value.call(0xc42009ca00, 0xc420048e10, 0x293, 0x1372569, 0x4, 0x155f1b8, 0x0, 0x0, 0x13711a0, 0x1, ...)
    /usr/local/Cellar/go/1.9.1/libexec/src/reflect/value.go:434 +0x906 fp=0xc420059340 sp=0xc420059068 pc=0x10b1c76
reflect.Value.Call(0xc42009ca00, 0xc420048e10, 0x293, 0x155f1b8, 0x0, 0x0, 0x150f5c0, 0xc420064300, 0xc420064300)
    /usr/local/Cellar/go/1.9.1/libexec/src/reflect/value.go:302 +0xa4 fp=0xc4200593a8 sp=0xc420059340 pc=0x10b1254
text/template.(*state).evalCall(0xc420059dd0, 0xc42009ca00, 0xc420048e10, 0x99, 0xc42009ca00, 0xc420048e10, 0x293, 0x150b800, 0xc42007eff0, 0x137307e, ...)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:670 +0x580 fp=0xc4200595e0 sp=0xc4200593a8 pc=0x12b3480
text/template.(*state).evalField(0xc420059dd0, 0xc42009ca00, 0xc420048e10, 0x99, 0x137307e, 0x2, 0x150b800, 0xc42007eff0, 0xc420048d00, 0x1, ...)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:560 +0xd38 fp=0xc420059940 sp=0xc4200595e0 pc=0x12b2d98
text/template.(*state).evalFieldChain(0xc420059dd0, 0xc42009ca00, 0xc420048e10, 0x99, 0xc42009ca00, 0xc420048e10, 0x99, 0x150b800, 0xc42007eff0, 0xc420048cf0, ...)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:528 +0x22a fp=0xc4200599f8 sp=0xc420059940 pc=0x12b1d2a
text/template.(*state).evalFieldNode(0xc420059dd0, 0xc42009ca00, 0xc420048e10, 0x99, 0xc42007eff0, 0xc420048d00, 0x1, 0x1, 0x0, 0x0, ...)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:492 +0x118 fp=0xc420059ab0 sp=0xc4200599f8 pc=0x12b1478
text/template.(*state).evalCommand(0xc420059dd0, 0xc42009ca00, 0xc420048e10, 0x99, 0xc42007efc0, 0x0, 0x0, 0x0, 0x348a0, 0x12fa0e0, ...)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:430 +0x676 fp=0xc420059b60 sp=0xc420059ab0 pc=0x12b0e26
text/template.(*state).evalPipeline(0xc420059dd0, 0xc42009ca00, 0xc420048e10, 0x99, 0xc420088280, 0xc42007f1d0, 0x30, 0x28)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:408 +0x115 fp=0xc420059c58 sp=0xc420059b60 pc=0x12b0315
text/template.(*state).walk(0xc420059dd0, 0xc42009ca00, 0xc420048e10, 0x99, 0x150b620, 0xc42007f020)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:234 +0x4af fp=0xc420059cd8 sp=0xc420059c58 pc=0x12af01f
text/template.(*state).walk(0xc420059dd0, 0xc42009ca00, 0xc420048e10, 0x99, 0x150b920, 0xc42007ef90)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:242 +0x11d fp=0xc420059d58 sp=0xc420059cd8 pc=0x12aec8d
text/template.(*Template).execute(0xc4200107c0, 0x1505a00, 0xc4200fe620, 0xc42009ca00, 0xc420048e10, 0x0, 0x0)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:197 +0x1f9 fp=0xc420059e28 sp=0xc420059d58 pc=0x12ae6c9
text/template.(*Template).Execute(0xc4200107c0, 0x1505a00, 0xc4200fe620, 0xc42009ca00, 0xc420048e10, 0x16, 0x194)
    /usr/local/Cellar/go/1.9.1/libexec/src/text/template/exec.go:180 +0x53 fp=0xc420059e70 sp=0xc420059e28 pc=0x12ae4a3
wenerme/tests/wcwork.TestData(0xc4201020f0)
    /Users/wener/go/src/wenerme/tests/wcwork/types_test.go:241 +0x31f fp=0xc420059fa8 sp=0xc420059e70 pc=0x12c459f
testing.tRunner(0xc4201020f0, 0x1387c28)
    /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:746 +0xd0 fp=0xc420059fd0 sp=0xc420059fa8 pc=0x10efc60
runtime.goexit()
    /usr/local/Cellar/go/1.9.1/libexec/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc420059fd8 sp=0xc420059fd0 pc=0x105cd41
created by testing.(*T).Run
    /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:789 +0x2de

goroutine 1 [chan receive]:
testing.(*T).Run(0xc420102000, 0x13732b1, 0x8, 0x1387c28, 0x107ab01)
    /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:790 +0x2fc
testing.runTests.func1(0xc420102000)
    /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:1004 +0x64
testing.tRunner(0xc420102000, 0xc420057de0)
    /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:746 +0xd0
testing.runTests(0xc4200e8320, 0x153b700, 0x5, 0x5, 0xc42009c820)
    /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:1002 +0x2d8
testing.(*M).Run(0xc420057f18, 0xc420057f70)
    /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:921 +0x111
main.main()

What's wrong with with reflect ?

  • 写回答

1条回答 默认 最新

  • dqrzot2791 2017-12-15 20:10
    关注

    you can pass reflect.Value directly into text/template and html/template execute method. If you change your code and pass them directly and use {.MyFace.Ok} everything works fine. I attach my code:

    package hello
    
    import (
        "bytes"
        "fmt"
        "html/template"
        "reflect"
        "testing"
    )
    
    func TestData(t *testing.T) {
        tpl, err := template.New("ok").Parse("{{.MyFace.Ok}}")
        if err != nil {
            panic(err)
        }
        buf := bytes.NewBuffer(nil)
        myTyp := reflect.StructOf([]reflect.StructField{
            {Name: "MyFace", Type: reflect.TypeOf((*MyFace)(nil)).Elem(), Index: []int{0}, Anonymous: true},
        })
        fmt.Println(myTyp)
        myVal := reflect.New(myTyp)
        myVal.Elem().Field(0).Set(reflect.New(reflect.TypeOf(testFace{})).Elem())
        err = tpl.Execute(buf, myVal.Elem()) // unexpected fault address
        //err = tpl.Execute(buf, &testDat{MyFace: MyFace(&testFace{})}) // works as expected
        if err != nil {
            panic(err)
        }
        fmt.Println(buf.String())
    }
    
    type testData struct {
        MyFace
    }
    type testFace struct {
        i int
    }
    
    func (testFace) Ok() string {
        return "All right"
    }
    
    type MyFace interface {
        Ok() string
    }
    

    but as you can test with use myVal.Elem().Interface() in above code all of your problems because go cannot find Ok method on your passed interface.

    As you can see in reflect.StructOf documentation StructOf currently does not generate wrapper methods for embedded fields. This limitation may be lifted in a future version.

    评论

报告相同问题?

悬赏问题

  • ¥15 matlab中使用gurobi时报错
  • ¥15 WPF 大屏看板表格背景图片设置
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂