1. Write it first

In last year’s coding, THE author used two libraries that are relatively easy to use, which are recorded here for future use and also for reference of those who have such requirements.

  • Golang Map to Structure library – github.com/mitchellh/m…

  • Golang JSON Validation library – github.com/go-playgrou…

2. mapstructure

2.1 use

Decode the generic map[string]interface{} into the corresponding Go structure.

Note: When Restful API body is parsed, it is usually decoded to map[string]interface{} using the standard Encoding/JSON library, and then converted to the Go structure using the MapStructure library.

The advantage of this additional transformation is that when the API body definition is incompatible, it does not affect the original parsing structure compared to defining the body structure directly.

2.2 example

There are plenty of articles on Google detailing the use of this library, so I won’t repeat them here, except to mention the pit points used here.

package main

import (
	"fmt"

	"github.com/mitchellh/mapstructure"
)

type School struct {
	name string
}

type Person struct {
	Name    string
	Address string
	Phones  []string
	XInfo   string `json:"x-info"`
	School  School
}

func DecodesExample(a) {
	m := map[string]interface{} {"name":    "xiyan"."address": "earth"."x-info":  "not-parse"."phones":  []string{"12345678"."87654321"}, // object type
		"school":  School{name: "xy"},               // nested structure
	}
	var p Person
	err := mapstructure.Decode(m, &p)
	iferr ! =nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%#v", p)
}

func main(a) {
	DecodesExample()
}

Copy the code

Output:

 mapToStruct $>go run main.go
main.Person{Name:"xiyan", Address:"earth", Phones:[]string{"12345678", "87654321"}, XInfo:"", School:main.School{name:"xy"}}
Copy the code

2.3 pit

The example in 2.2 shows how to convert a map[stirng]interface{} structure to a custom GO structure.

  • A map can contain object types such as slice

  • Maps can contain custom structue types

  • Keys containing hyphens (-) will not be parsed, but keys containing ‘_’ will be parsed

    Note: see “X-info “: “not-parse”, I have not found the reason, guess it is because go variable names contain letters, numbers and underscores.

3. validator

3.1 use

Data validation is a common problem in Web applications. The package Validator is a common one. The principle is to write the verification rules in the tag corresponding to the struct field, and then obtain the tag of the struct through reflection to realize data verification.

3.2 example

package main

import (
	"fmt"

	"github.com/go-playground/validator/v10"
)

func BasicExample(a) {
	type Person struct {
		Name string `json:"name" validate:"required"`
		Age  int64  `json:"age" validate:"required"`
	}
	p := Person{
		Name: "",
		Age:  18,
	}
	v := validator.New()
	err := v.Struct(p)
	iferr ! =nil {
		fmt.Println(err)
		return
	}
	fmt.Println(p)
}

func FieldExample(a) {
	type Person struct {
		// Note: There must be only ", "and no space between required and nameValidator
		Name string `json:"name" validate:"required,nameValidator"`
		Age  int64  `json:"age" validate:"required"`
	}

	nameValidator := func(f validator.FieldLevel) bool {
		returnf.Field().String() ! ="xiyan"
	}

	v := validator.New()
	v.RegisterValidation("nameValidator", nameValidator)

	p := Person{
		Name: "xiyan",
		Age:  19,
	}
	err := v.Struct(p)
	iferr ! =nil {
		fmt.Println(err)
		return
	}
	fmt.Println(p)
}

func SturctLevelExample(a) {
	type Person struct {
		Name string `json:"name" validate:"required"`
		Age  int64  `json:"age" validate:"required"`
	}

	structValidator := func(f validator.StructLevel) {
		p := f.Current().Interface().(Person)
		if p.Name == "xiyan" {
			f.ReportError(p.Name, "Name"."name"."name"."")}if p.Age > 80 {
			f.ReportError(p.Age, "Age"."age"."age"."")

		}
	}

	v := validator.New()
	v.RegisterStructValidation(structValidator, Person{})

	p := Person{
		Name: "xiyan",
		Age:  81,
	}
	err := v.Struct(p)
	iferr ! =nil {
		fmt.Println(err)
		return
	}
	fmt.Println(p)
}

func main(a) {
	// FieldExample()
	SturctLevelExample()
}

Copy the code

The above example consists of three parts:

  • Define the validation rule – BasicExample – directly in the Tag section defined by Sturcture
  • Define a specific function to verify the structure Field Field — FieldExample
  • Verification of specific functions for the whole structure – SturctLevelExample

Here, the author uses the verification method of SturctLevelExample, but the problem is that the specific error identified cannot be thrown to the upper layer, the upper layer can only see the error of the specified field, and the specific value error cannot be identified.

Note: There are always more methods than problems. Here, the author used a dirty method to expose the error fields through the tag field, and then removed the tag from the upper error field.

3.3 pit

Concrete example

func SturctLevelExample(a) {
	type Person struct {
		Name string `json:"name" validate:"required"`
		Age  int64  `json:"age" validate:"required"`
	}

	structValidator := func(f validator.StructLevel) {
		p := f.Current().Interface().(Person)
		if p.Name == "xiyan" {
			f.ReportError(p.Name, "Name"."name"."name should not equal xiyan"."")}if p.Age > 80 {
			f.ReportError(p.Age, "Age"."age"."age should not greater than 80"."")

		}
	}

	v := validator.New()
	v.RegisterStructValidation(structValidator, Person{})

	p := Person{
		Name: "xiyan",
		Age:  81,
	}
	err := v.Struct(p)
	iferr ! =nil {
		for _, e := range err.(validator.ValidationErrors) {
			fmt.Println(e.Tag())
		}
		return
	}
	fmt.Println(p)
}

func main(a) {
	SturctLevelExample()
}

Copy the code

Output:

validator $> go run main.go
name should not equal xiyan
age should not greater than 80
Copy the code

4)

Today is a good day, I hope those who work overtime can leave early.

  • I hope you understand that growing up means you can do more of the things you want to do instead of being forced to do more of the things you don’t want to do.
  • I hope you can live a happy life, do what you like, drink and breathe when you are tired, live the life you want.
  • Like to fight for, get to cherish, miss to forget.

One of the rules of happiness in life is to consider how good the food tastes when you eat it.

5. Reference materials

  • Converting map to struct
  • Go one library of mapStructure per day
  • Golang data validation Validator
  • Golang common library: Field parameter validation library – Validator used