gen icon indicating copy to clipboard operation
gen copied to clipboard

unknow param type: &{Func:4040 TypeParams:<nil> Params:0x14000466a50 Results:<nil>}

Open itcuihao opened this issue 2 years ago • 11 comments

Your Question

package users

import (
	"go.uber.org/zap"
	"my-wifi/pkg/logs"

	"gorm.io/gen"
	"gorm.io/gorm"
)

// Dynamic SQL
type Querier interface {
	// SELECT * FROM @@table WHERE uuid = @uuid{{if phone !=""}} AND phone = @phone{{end}}
	//FilterWithUUIDAndPhone(uuid, phone string) ([]gen.T, error)
	// SELECT * FROM @@table WHERE uuid = @uuid{{if username !=""}} AND username = @username{{end}}
	//FilterWithUUIDAndName(uuid, username string) ([]gen.T, error)
}

type User struct {
	Name string
}

func GenUser(db *gorm.DB) error {
	//if err := db.AutoMigrate(models.Users{}); err != nil {
	//	logs.Z.Error("gen", zap.Error(err))
	//	return err
	//}
	logs.Z.Info("gen", zap.Any("user", "AutoMigrate"))
	g := gen.NewGenerator(gen.Config{
		OutPath: "../../internal/dao/users",
		Mode:    gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
	})

	g.UseDB(db) // reuse your gorm db
	logs.Z.Info("gen", zap.Any("user", "UseDB"))
	// Generate basic type-safe DAO API for struct `model.User` following conventions
	g.ApplyBasic(User{})
	logs.Z.Info("gen", zap.Any("user", "ApplyBasic"))
	// Generate Type Safe API with Dynamic SQL defined on Querier interface for `model.User` and `model.Company`
	g.ApplyInterface(func(Querier) {}, User{})
	logs.Z.Info("gen", zap.Any("user", "ApplyInterface"))
	// Generate the code
	g.Execute()
	logs.Z.Info("gen", zap.Any("user", "Execute"))
	return nil
}

exec res

[my-wifi]2023/06/26 - 00:09:48.124      info    /gorm.go:25       db      {"init": "success"}
[my-wifi]2023/06/26 - 00:09:48.124      info   users.tpl.go:28    gen     {"user": "AutoMigrate"}
[my-wifi]2023/06/26 - 00:09:48.124      info   users.tpl.go:35    gen     {"user": "UseDB"}
[my-wifi]2023/06/26 - 00:09:48.124      info   users.tpl.go:38    gen     {"user": "ApplyBasic"}
2023/06/26 00:09:48 unknow param type: &{Func:4040 TypeParams:<nil> Params:0x14000466a50 Results:<nil>}

itcuihao avatar Jun 25 '23 16:06 itcuihao

@itcuihao 是用的最新版吗,本地试了下没问题

qqxhb avatar Jun 26 '23 04:06 qqxhb

好的,估计要回家试试,在公司没有这个错误,这个错误与什么有关呢,给点排查的线索,或者如何debug,ApplyInterface报的,不过没看到是啥问题

itcuihao avatar Jun 26 '23 06:06 itcuihao

@itcuihao 是用的最新版吗,本地试了下没问题

@qqxhb 有限制只能执行一次 Gen 方法吗,修改 model,后再执行就会必现此错误。

itcuihao avatar Jun 27 '23 02:06 itcuihao

ApplyInterface

用官网例子,此方法重复执行时会出发此问题

itcuihao avatar Jun 27 '23 06:06 itcuihao

ApplyInterface

用官网例子,此方法重复执行时会出发此问题

没有限制。每次都是覆盖更新的

qqxhb avatar Jun 27 '23 06:06 qqxhb

连续执行两次,添加了打印信息

eddy/cmd/gen via 🐹 took 3s 
❯ go run main.go
path 0
path 0
path 1
2023/06/27 14:15:23 Start generating code.
2023/06/27 14:15:23 generate query file: /Users/c/mygo/ch/demo/eddy/internal/dao/merchant/merchant_wifis.gen.go
2023/06/27 14:15:23 generate query file: /Users/c/mygo/ch/demo/eddy/internal/dao/merchant/merchants.gen.go
2023/06/27 14:15:23 generate query file: /Users/c/mygo/ch/demo/eddy/internal/dao/merchant/gen.go
2023/06/27 14:15:23 Generate code done.

eddy/cmd/gen via 🐹 took 2s 
❯ go run main.go
path 0
path 0
path 1
&ast.FuncType{Func:2123, TypeParams:(*ast.FieldList)(nil), Params:(*ast.FieldList)(0xc00034d380), Results:(*ast.FieldList)(nil)}
2139
0 &ast.Ident{NamePos:2120, Name:"fc", Obj:(*ast.Object)(0xc00030dea0)}
2023/06/27 14:15:50 unknow param type1: &{Func:2123 TypeParams:<nil> Params:0xc00034d380 Results:<nil>}
exit status 1

// 错误行 gen/internal/parse/parse.go
func (p *Param) astGetParamType(param *ast.Field) {

	switch v := param.Type.(type) {
	case *ast.Ident:
		p.Type = v.Name
		if v.Obj != nil {
			p.Package = "UNDEFINED" // set a placeholder
		}
	case *ast.SelectorExpr:
		p.astGetEltType(v)
	case *ast.ArrayType:
		p.astGetEltType(v.Elt)
		p.IsArray = true
	case *ast.Ellipsis:
		p.astGetEltType(v.Elt)
		p.IsArray = true
	case *ast.MapType:
		p.astGetMapType(v)
	case *ast.InterfaceType:
		p.Type = "interface{}"
	case *ast.StarExpr:
		p.IsPointer = true
		p.astGetEltType(v.X)
	default:
		fmt.Printf("%#v\n", param.Type)
		fmt.Printf("%#v\n", param.Type.End())
		for i, n := range param.Names {

			fmt.Printf("%d %#v\n", i, n)
		}

		log.Fatalf("unknow param type1: %+v", v)
	}
}

执行代码


// Dynamic SQL
type Querier interface {
	// SELECT * FROM @@table WHERE username = @name{{if role !=""}} AND role = @role{{end}}
	//FilterWithNameAndRole(username, role string) ([]gen.T, error)

	// SELECT * FROM @@table WHERE name = @name
	FilterWithName(name string) ([]gen.T, error)
}

func Gen(gormdb *gorm.DB) {

	g := gen.NewGenerator(gen.Config{
		OutPath: "../../internal/dao/merchant",
		Mode:    gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
	})

	g.UseDB(gormdb) // reuse your gorm db

	// Generate basic type-safe DAO API for struct `model.User` following conventions
	g.ApplyBasic(Merchant{})
	g.ApplyBasic(MerchantWifi{})

	// Generate Type Safe API with Dynamic SQL defined on Querier interface for `model.User` and `model.Company`
	g.ApplyInterface(func(Querier) {},Merchant{},MerchantWifi{})

	// Generate the code
	g.Execute()
}

type Merchant struct {
	Name string
}

type MerchantWifi struct {
	Name string
}

func main() {
	gormdb, _ := gorm.Open(mysql.Open("c:123@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"))
	//gormdb.AutoMigrate(models.User{})
	
	merchant.Gen(gormdb)
}

itcuihao avatar Jun 27 '23 06:06 itcuihao

@itcuihao 本地最新版本跑了两次都没复现

qqxhb avatar Jun 27 '23 06:06 qqxhb

@itcuihao 本地最新版本跑了两次都没复现

可否麻烦贴一下代码,我粘贴试试,我也觉得挺奇怪的,注释调就好了 ApplyInterface,不知道是不是我写的不对 @qqxhb

itcuihao avatar Jun 29 '23 09:06 itcuihao

g.ApplyInterface(func(Querier) {},Merchant{},MerchantWifi{})

// GEN Guideline: https://bytedance.feishu.cn/wiki/wikcnbYLEL78aOYLBsT2ExUGiEd

// generate code func main() { //init db mysql.Init() db := mysql.DB(context.Background())

// specify the output directory (default: "./query")
// ### if you want to query without context constrain, set mode gen.WithoutContext ###
g := gen.NewGenerator(gen.Config{
	OutPath:      "../../dal/query",
	ModelPkgPath: "../../model/db_model",
	Mode:         gen.WithDefaultQuery,
	/* Mode: gen.WithoutContext,*/
	//if you want the nullable field generation property to be pointer type, set FieldNullable true
	/* FieldNullable: true,*/
})

// reuse the database connection in Project or create a connection here
// if you want to use GenerateModel/GenerateModelAs, UseDB is necessray or it will panic
g.UseDB(db)

// apply basic crud api on structs or table models which is specified by table name with function
// GenerateModel/GenerateModelAs. And generator will generate table models' code when calling Excute.
// g.ApplyBasic(model.User{}, g.GenerateModel("company"), g.GenerateModelAs("people", "Person", gen.FieldIgnore("address")))
g.ApplyInterface(func(Querier) {},Merchant{},MerchantWifi{})
// apply diy interfaces on structs or table models
// g.ApplyInterface(func(method model.Method) {}, model.User{}, g.GenerateModel("company"))

// execute the action of code generation
g.Execute()

} // Dynamic SQL type Querier interface { // SELECT * FROM @@table WHERE username = @name{{if role !=""}} AND role = @role{{end}} //FilterWithNameAndRole(username, role string) ([]gen.T, error)

// SELECT * FROM @@table WHERE name = @name
FilterWithName(name string) ([]gen.T, error)

}

type Merchant struct { Name string }

type MerchantWifi struct { Name string }

qqxhb avatar Jun 29 '23 09:06 qqxhb

g.ApplyInterface(func(query.UserQuerier) {}, model.User{}) vs g.ApplyInterface(func(UserQuerier) {}, model.User{}) 通过import引入的UserQuerier会导致报错的。

Tooooommy avatar Sep 23 '23 19:09 Tooooommy

ApplyInterface

用官网例子,此方法重复执行时会出发此问题

解决了吗?我也出现了这样的问题

uzziahlin avatar Nov 23 '23 03:11 uzziahlin