Sửa lỗi Go Template: "can't evaluate field Username in type main.User"

beginner🔷 Go2026-06-18| Go 1.18+, Linux/macOS/Windows, các gói html/template hoặc text/template

Error Message

template: mytemplate:5:8: executing "mytemplate" at <.Username>: can't evaluate field Username in type main.User
#template#html/template#struct#reflection

Thông báo lỗiBạn làm mới ứng dụng web Go của mình, mong đợi một bảng điều khiển được cá nhân hóa, nhưng thay vào đó lại gặp lỗi 500. Kiểm tra nhật ký (logs) sẽ thấy lỗi cụ thể sau:

template: mytemplate:5:8: executing "mytemplate" at : can't evaluate field Username in type main.User

Điều này xảy ra vì engine template đã cố gắng truy cập vào một phần dữ liệu mà nó không thể nhìn thấy. Thông thường, nguyên nhân là do một trường riêng tư (private field) hoặc hiểu sai về cách ngữ cảnh "dấu chấm" (dot context) thay đổi trong quá trình thực thi.

Nguyên nhân gốc rễ: Trường Exported và UnexportedCác quy tắc về khả năng hiển thị trong Go rất đơn giản: chữ hoa là công khai (exported), chữ thường là riêng tư (unexported). Gói html/template sử dụng reflection để đọc các struct của bạn trong thời gian chạy. Tuy nhiên, reflection không thể vượt qua tính bảo mật của Go để truy cập các trường riêng tư.

Hãy tưởng tượng struct của bạn trông như thế này:

type User struct {
    username string // Riêng tư (Private)
    Email    string // Công khai (Public)
}

Ngay cả khi bạn truyền dữ liệu chính xác, {{.username}} vẫn sẽ thất bại. Engine coi các trường riêng tư như thể chúng không tồn tại.

Cách sửa lỗi### 1. Viết hoa các trường trong StructCách khắc phục nhanh nhất là thay đổi định nghĩa struct của bạn. Đảm bảo mọi trường được sử dụng trong template đều bắt đầu bằng một chữ cái viết hoa.

type User struct {
    Username string
    Email    string
}

Cập nhật template của bạn cho khớp: <p>Xin chào, {{.Username}}!</p>. Thay đổi đơn giản này giải quyết được 90% các lỗi loại này.

2. Làm chủ ngữ cảnh "Dấu chấm" (Dot Context)"Dấu chấm" (.) đại diện cho con trỏ hiện tại của bạn. Nó thay đổi khi bạn vào một khối {{range}} hoặc {{with}}. Nếu bạn lặp qua một danh sách các bài viết, dấu chấm không còn là dữ liệu cấp cao nhất của bạn nữa; nó trở thành bài viết cụ thể mà bạn đang xử lý.

{{range .Posts}}
    <p>Đăng bởi: {{.User.Username}}</p> <!-- Đoạn này thường thất bại! -->
{{end}}

Nếu User là một thuộc tính của dữ liệu toàn cục chứ không phải của struct Post, template sẽ bị lỗi. Hãy sử dụng $ để quay lại gốc dữ liệu ban đầu được truyền vào template:

{{range .Posts}}
    <li>Được viết bởi: {{$.User.Username}}</li> <!-- Cách này hoạt động! -->
{{end}}

3. Kiểm tra tính phân biệt chữ hoa chữ thườngGo rất khắt khe với việc phân biệt chữ hoa chữ thường. Nếu struct của bạn định nghĩa Username nhưng template HTML gọi {{.UserName}} (lưu ý chữ 'N' viết hoa), việc đánh giá sẽ thất bại ngay lập tức. Go template không cung cấp tính năng "khớp mờ" (fuzzy matching) cho tên trường.

Xác minh cách sửa lỗiĐừng khởi động lại toàn bộ máy chủ chỉ để kiểm tra một lỗi nhỏ. Hãy sử dụng một script độc lập nhanh chóng để xác nhận template được parse và thực thi chính xác.

package main

import (
    "html/template"
    "os"
)

type User struct {
    Username string
}

func main() {
    const doc = `<p>Xin chào, {{.Username}}!</p>`
    t := template.Must(template.New("test").Parse(doc))
    
    // Kiểm tra với dữ liệu thực tế
    err := t.Execute(os.Stdout, User{Username: "Alice"})
    if err != nil {
        panic(err)
    }
}

Mẹo phòng tránh- Chạy go vet: Công cụ tích hợp này giúp phát hiện nhiều lỗi cú pháp template trước khi bạn chạy mã.- Tránh sử dụng map chung (generic maps): Truyền map[string]any tuy tiện lợi nhưng nguy hiểm. Các struct có kiểu dữ liệu mạnh (strongly typed) cung cấp hỗ trợ IDE tốt hơn và giúp bạn phát hiện các lỗi đánh máy trong quá trình phát triển.- Tiêu chuẩn hóa việc đặt tên: Nếu JSON của bạn sử dụng user_name, struct sử dụng Username và template sử dụng UserName, bạn đang tự chuốc lấy rắc rối. Hãy giữ tên gọi nhất quán giữa tất cả các lớp.

Related Error Notes