Golang错误信息中如何显示行号

Golang错误信息中如何显示行号 当我使用 validate.struct() 后,如果我的内容存在一些验证错误,该函数会返回这些 ValidationErrors。 是否有可能向用户显示该特定元素所在的行号? 我正在使用 yaml 文件来解析和验证内容。如果有任何可能性,请给出建议?

func main() {
    fmt.Println("hello world")
}
1 回复

更多关于Golang错误信息中如何显示行号的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中,当使用validate.Struct()进行验证时,可以通过自定义错误消息或扩展验证错误来包含行号信息。以下是一个示例,展示如何将YAML行号与验证错误关联:

package main

import (
	"fmt"
	"gopkg.in/yaml.v3"
	"github.com/go-playground/validator/v10"
)

type Config struct {
	Name  string `yaml:"name" validate:"required"`
	Email string `yaml:"email" validate:"email"`
	Age   int    `yaml:"age" validate:"gte=18"`
}

type ValidationErrorWithLine struct {
	Field   string
	Tag     string
	Value   interface{}
	Line    int
	Message string
}

func main() {
	yamlContent := `
name: John
email: invalid-email
age: 16
`

	var config Config
	var node yaml.Node
	
	// 解析YAML并保留节点信息
	err := yaml.Unmarshal([]byte(yamlContent), &node)
	if err != nil {
		panic(err)
	}
	
	// 从根节点提取配置
	err = node.Decode(&config)
	if err != nil {
		panic(err)
	}

	validate := validator.New()
	err = validate.Struct(config)
	
	if err != nil {
		if validationErrors, ok := err.(validator.ValidationErrors); ok {
			errorsWithLines := make([]ValidationErrorWithLine, 0)
			
			// 遍历YAML节点查找字段位置
			var findFieldLine func(*yaml.Node, string) int
			findFieldLine = func(n *yaml.Node, fieldName string) int {
				if n.Kind == yaml.MappingNode {
					for i := 0; i < len(n.Content); i += 2 {
						keyNode := n.Content[i]
						if keyNode.Value == fieldName {
							return keyNode.Line
						}
					}
				}
				return 0
			}
			
			// 为每个验证错误添加行号
			for _, validationErr := range validationErrors {
				fieldName := validationErr.Field()
				line := findFieldLine(node.Content[0], fieldName)
				
				errorsWithLines = append(errorsWithLines, ValidationErrorWithLine{
					Field:   fieldName,
					Tag:     validationErr.Tag(),
					Value:   validationErr.Value(),
					Line:    line,
					Message: fmt.Sprintf("Field '%s' failed validation '%s' at line %d", 
						fieldName, validationErr.Tag(), line),
				})
			}
			
			// 显示带行号的错误信息
			for _, errWithLine := range errorsWithLines {
				fmt.Printf("Error at line %d: %s\n", errWithLine.Line, errWithLine.Message)
			}
		}
	}
}

如果需要更精确的行号跟踪,可以考虑使用自定义验证器:

type ConfigWithLine struct {
	Name  string `yaml:"name" validate:"required"`
	Email string `yaml:"email" validate:"email"`
	Age   int    `yaml:"age" validate:"gte=18"`
	Lines map[string]int `yaml:"-"`
}

func validateWithLineNumbers(yamlContent string) {
	var node yaml.Node
	err := yaml.Unmarshal([]byte(yamlContent), &node)
	if err != nil {
		panic(err)
	}

	configWithLine := ConfigWithLine{
		Lines: make(map[string]int),
	}

	// 提取字段和行号
	if node.Content[0].Kind == yaml.MappingNode {
		content := node.Content[0].Content
		for i := 0; i < len(content); i += 2 {
			keyNode := content[i]
			valueNode := content[i+1]
			
			switch keyNode.Value {
			case "name":
				valueNode.Decode(&configWithLine.Name)
				configWithLine.Lines["Name"] = keyNode.Line
			case "email":
				valueNode.Decode(&configWithLine.Email)
				configWithLine.Lines["Email"] = keyNode.Line
			case "age":
				valueNode.Decode(&configWithLine.Age)
				configWithLine.Lines["Age"] = keyNode.Line
			}
		}
	}

	validate := validator.New()
	err = validate.Struct(configWithLine)
	
	if err != nil {
		if validationErrors, ok := err.(validator.ValidationErrors); ok {
			for _, validationErr := range validationErrors {
				fieldName := validationErr.Field()
				if line, exists := configWithLine.Lines[fieldName]; exists {
					fmt.Printf("Validation error for field '%s' at line %d: %s\n",
						fieldName, line, validationErr.Tag())
				}
			}
		}
	}
}

这些示例展示了如何将YAML解析的行号信息与验证错误关联,从而向用户显示具体的行号位置。

回到顶部