golang treasure house recommendation

1. Write at the beginning

When I was coding last year, I found two easy-to-use libraries and recorded them here for reuse later. At the same time, it is also convenient for those who have needs in this regard.

  • Library of golang map to structure - https://github.com/mitchellh/mapstructure

  • golang json verification Library - https://github.com/go-playground/validator

2. mapstructure

2.1 purpose

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

Note: when parsing Restful api body, the standard encoding/json library is generally used to decode the data into map[string]interface {} type, and then mapstructure library is used to convert it into Go structure.

The advantage of the above one-time conversion is that when the api body definitions are incompatible, compared with directly defining the body structure, this method will not affect the original parsing structure.

2.2 examples

There are many articles about the use of this library on google. I won't repeat them here, but just talk about the pits 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() {
	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)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%#v", p)
}

func main() {
	DecodesExample()
}

Output:

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

2.3 pit description

The example in 2.2 shows how to convert the structure of a map[stirng]interface {} into a custom go structure.

  • A map can contain object types such as slice

  • A map can contain a custom structure type

  • If the key contained in the map contains - dash, the field will not be resolved successfully, but contains' ' sure

    Note: see "x-info": "not parse". The author has not found the reason yet. It is speculated that the name of go variable contains letters, numbers and underscores.

3. validator

3.1 purpose

In web applications, we often encounter the problem of data validation, and the package is commonly used validator . The principle is to write the verification rules in the corresponding field tag of struct, and then obtain the tag of struct through reflection to realize data verification.

3.2 examples

package main

import (
	"fmt"

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

func BasicExample() {
	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)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(p)
}

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

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

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

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

func SturctLevelExample() {
	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)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(p)
}

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

The above example includes three parts:

  • Directly define the verification rule - BasicExample in the tag part of the sturcture definition
  • Define a specific function to verify the Field field of structure - FieldExample
  • Verify specific functions for the whole structure - SturctLevelExample

Here, the author uses the verification method of SturctLevelExample. The problem is that the specific error identified cannot be thrown to the upper layer. The upper layer can only view the error of the specified field. Where the specific value is wrong cannot be identified.

Note: there are always more methods than problems. Here, in the use of exposing errors, the author uses a dirty method to expose the wrong field through the tag field, and then take out the tag from the upper error field.

3.3 pit description

Specific examples

func SturctLevelExample() {
	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)
	if err != nil {
		for _, e := range err.(validator.ValidationErrors) {
			fmt.Println(e.Tag())
		}
		return
	}
	fmt.Println(p)
}

func main() {
	SturctLevelExample()
}

Output:

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

4. Broken thoughts

Today is a good day. I hope everyone who works overtime can get off work early.

  • I hope you can understand that when you grow up, you can do more things you want to do, rather than being forced to do more things you don't want to do.
  • I hope you can live happily, do what you like to do, drink and blow the wind when you are tired, and live the life you want.
  • Fight for what you like, cherish what you get, and forget what you miss.

One of the rules of happiness in life is to consider whether the food is delicious when eating.

5. References

Keywords: Go Back-end

Added by mizkit73 on Mon, 14 Feb 2022 12:29:06 +0200