Skip to content

Commit

Permalink
fix generic check with slice for ghttp (#2850)
Browse files Browse the repository at this point in the history
  • Loading branch information
WankkoRee authored Aug 16, 2023
1 parent ea6a773 commit 3df5969
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 3 deletions.
8 changes: 5 additions & 3 deletions net/ghttp/ghttp_server_service_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,12 @@ func (s *Server) checkAndCreateFuncInfo(f interface{}, pkgPath, structName, meth

func trimGeneric(structName string) string {
var (
leftBraceIndex = strings.Index(structName, "[")
rightBraceIndex = strings.Index(structName, "]")
leftBraceIndex = strings.LastIndex(structName, "[") // for generic, it is faster to start at the end than at the beginning
rightBraceIndex = strings.LastIndex(structName, "]")
)
if leftBraceIndex == -1 || rightBraceIndex == -1 {
if leftBraceIndex == -1 || rightBraceIndex == -1 { // not found '[' or ']'
return structName
} else if leftBraceIndex+1 == rightBraceIndex { // may be a slice, because generic is '[X]', not '[]'
return structName
}
return structName[:leftBraceIndex]
Expand Down
77 changes: 77 additions & 0 deletions net/ghttp/ghttp_z_unit_feature_router_strict_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,80 @@ func Test_Custom_Slice_Type_Attribute(t *testing.T) {
)
})
}

func Test_Router_Handler_Strict_WithGeneric(t *testing.T) {
type TestReq struct {
Age int
}
type TestGeneric[T any] struct {
Test T
}
type Test1Res struct {
Age TestGeneric[int]
}
type Test2Res TestGeneric[int]
type TestGenericRes[T any] struct {
Test T
}

s := g.Server(guid.S())
s.Use(ghttp.MiddlewareHandlerResponse)
s.BindHandler("/test1", func(ctx context.Context, req *TestReq) (res *Test1Res, err error) {
return &Test1Res{
Age: TestGeneric[int]{
Test: req.Age,
},
}, nil
})
s.BindHandler("/test1_slice", func(ctx context.Context, req *TestReq) (res []Test1Res, err error) {
return []Test1Res{
Test1Res{
Age: TestGeneric[int]{
Test: req.Age,
},
},
}, nil
})
s.BindHandler("/test2", func(ctx context.Context, req *TestReq) (res *Test2Res, err error) {
return &Test2Res{
Test: req.Age,
}, nil
})
s.BindHandler("/test2_slice", func(ctx context.Context, req *TestReq) (res []Test2Res, err error) {
return []Test2Res{
Test2Res{
Test: req.Age,
},
}, nil
})

s.BindHandler("/test3", func(ctx context.Context, req *TestReq) (res *TestGenericRes[int], err error) {
return &TestGenericRes[int]{
Test: req.Age,
}, nil
})
s.BindHandler("/test3_slice", func(ctx context.Context, req *TestReq) (res []TestGenericRes[int], err error) {
return []TestGenericRes[int]{
TestGenericRes[int]{
Test: req.Age,
},
}, nil
})

s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()

time.Sleep(100 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
client := g.Client()
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))

t.Assert(client.GetContent(ctx, "/test1?age=1"), `{"code":0,"message":"","data":{"Age":{"Test":1}}}`)
t.Assert(client.GetContent(ctx, "/test1_slice?age=1"), `{"code":0,"message":"","data":[{"Age":{"Test":1}}]}`)
t.Assert(client.GetContent(ctx, "/test2?age=2"), `{"code":0,"message":"","data":{"Test":2}}`)
t.Assert(client.GetContent(ctx, "/test2_slice?age=2"), `{"code":0,"message":"","data":[{"Test":2}]}`)
t.Assert(client.GetContent(ctx, "/test3?age=3"), `{"code":0,"message":"","data":{"Test":3}}`)
t.Assert(client.GetContent(ctx, "/test3_slice?age=3"), `{"code":0,"message":"","data":[{"Test":3}]}`)
})
}

0 comments on commit 3df5969

Please sign in to comment.