Go模板渲染报错:无法访问Category结构体未导出字段category_id
解决Go模板无法访问结构体字段的问题
问题原因
Go语言中,小写开头的结构体字段属于未导出字段,仅能在其定义所在的包内部访问。而Go的模板引擎(如text/template)属于标准库包,属于外部包范畴,无法直接访问未导出字段。这就是你调用{{ $element.category_id }}报错的原因;直接输出{{ $element }}能看到数据,是因为结构体默认的格式化逻辑(如fmt包的处理)可以显示未导出字段,但模板引擎本身不支持直接调用这类字段。
解决方案
将结构体的字段名改为首字母大写(转为导出字段),同时同步修改所有引用该字段的代码:
- 修改
Category结构体的字段定义:
type Category struct { CategoryID int // 首字母大写,成为导出字段 }
- 更新数据库查询的
Scan语句,匹配新字段名:
result.Scan(&objCategory.CategoryID)
- 在HTML模板中使用新的导出字段名:
<option value="eded">{{ $element.CategoryID }}</option>
修改后的完整代码示例
Category Handler代码
type PageProps struct { Categories []Category } type Category struct { CategoryID int // 导出字段 } type CategorydHandler struct { PageData PageProps } func Instantiate(pageProps PageProps) *CategorydHandler { return &CategorydHandler{ PageData: pageProps, } } func (pageData *CategorydHandler) GetCategories() []Category { query := "select category_id from tblcategory order by category_id" // 明确指定字段,避免select *的潜在问题 result, err := db.Query(query) // 补充错误处理,防止运行时panic if err != nil { // 可根据业务需求添加日志或返回空切片 return nil } defer result.Close() // 遍历完成后关闭结果集 for result.Next() { var objCategory Category if err := result.Scan(&objCategory.CategoryID); err != nil { // 处理字段扫描错误,如跳过当前条目 continue } pageData.PageData.Categories = append(pageData.PageData.Categories, objCategory) } // 处理遍历结果集时的错误 if err := result.Err(); err != nil { // 错误处理逻辑,如日志记录 } return pageData.PageData.Categories }
HTML代码
<select multiple type="text"> {{ range $index, $element := .Categories }} <option value="{{ $element.CategoryID }}">{{ $element.CategoryID }}</option> {{ end }} </select>
额外提示
- 数据库查询建议明确指定字段,而非使用
select *,这样能避免表结构变更带来的适配问题,代码可读性也更强。 - 代码中务必补充错误处理逻辑,比如数据库查询、字段扫描的错误捕获,避免潜在的运行时异常。
内容的提问来源于stack exchange,提问作者Pankaj
相关产品推荐
相关产品推荐

