Go语言学习笔记——结构体中使用tag标记

本文介绍了Go语言中结构体使用tag标记的用途,包括json、xml编码以及form表单绑定的应用,并提供了gin框架下form数据绑定的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


golang结构体中使用tag标记

简介

我们可以在结构体的字段后面,添加一些对该字段的说明(元信息meta),程序通过反射解析这些信息并使用。

语法结构

`key:"value" key:"value"`

反引号括起来,key不加双引号,value加双引号,多个值中间用空格分开

快速入门

package main

import (
	"fmt"
	"reflect"
)

func main() {
	type S struct {
		F string `species:"gopher" color:"blue"`
	}

	//实例化结构体,在这里没有使用到,所以空实例化
	s := S{}

	//使用反射获得结构体的type类型
	st := reflect.TypeOf(s)

	//拿到第一个字段
	field := st.Field(0)

	//拿到tag里面的东西
	fmt.Println(field.Tag.Get("color"), field.Tag.Get("species"))
}

运行结果:

[Running] go run "e:\golang开发学习\go_pro\main.go"
blue gopher

[Done] exited with code=0 in 1.234 seconds

常见应用

应用json编码

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"
)

//一般我们字段名都是大写的,但是我们json里面都是小写的,这里就可以通过tag来使用小写来知道大写的字段
type User struct {
	Name      string    `json:"name"`
	Password  string    `json:"password"`
	CreatedAt time.Time `json:"createdAt"`
}

func main() {
	u := &User{
		Name:      "Psych",
		Password:  "123456",
		CreatedAt: time.Now(),
	}

	out, err := json.MarshalIndent(u, "", "	")
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	fmt.Println(string(out))
}

运行结果:

[Running] go run "e:\golang开发学习\go_pro\main.go"
{
	"name": "Psych",
	"password": "123456",
	"createdAt": "2022-09-09T16:58:24.0876915+08:00"
}

[Done] exited with code=0 in 1.136 seconds

应用xml编码

package main

import (
	"encoding/xml"
	"fmt"
	"os"
)

func main() {
	type Address struct {
		City, State string
	}
	type Person struct {
		XMLName   xml.Name `xml:"person"`
		Id        int      `xml:"id,attr"` //attr代表属性
		FirstName string   `xml:"name>first"`
		LastName  string   `xml:"name>last"` //>代表子节点
		Age       int      `xml:"age"`
		Height    float32  `xml:"height,omitempty"`
		Married   bool
		Address
		Comment string `xml:"comment"`
	}
	v := &Person{Id: 13, FirstName: "Wong", LastName: "Psych", Age: 18}
	v.Comment = "注释."
	v.Address = Address{"四川", "成都"}
	output, err := xml.MarshalIndent(v, "", "	")
	if err != nil {
		fmt.Printf("error:%v\n", err)
	}
	_, err = os.Stdout.Write(output)
	if err != nil {
		return
	}
}

运行结果:

[Running] go run "e:\golang开发学习\go_pro\main.go"
<person id="13">
	<name>
		<first>Wong</first>
		<last>Psych</last>
	</name>
	<age>18</age>
	<Married>false</Married>
	<City>四川</City>
	<State>成都</State>
	<comment>注释.</comment>
</person>
[Done] exited with code=0 in 1.248 seconds

应用form表单绑定

可以写多个tag标签,使用空格分开

type Channel struct {
	Id      uint64 `form:"id" gorm:"primaryKey"`
	Title   string `form:"title" gorm:"title"`
	Slug    string `form:"slug" gorm:"slug"`
	Content string `form:"content" gorm:"content"`
	Status  int    `form:"status" gorm:"status"`
	Weight  int    `form:"weight" gorm:"weight"`
}

gin框架form和数据绑定

package main

import "C"
import (
	"github.com/gin-gonic/gin"
	"net/http"
)

type Login struct {
  //form:表单中的name一般是小写的id,json:前后端分离返回给前端的参数,binding:字段校验
	User     string `form:"user" json:"user" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

func main() {
	router := gin.Default()

	// 绑定 JSON ({"user":"manu","password":"123"})
	router.POST("/loginJSON", func(c *gin.Context) {
		var json Login
		if err := c.ShouldBindJSON(&json); err == nil {
			if json.User == "manu" && json.Password == "123" {
				c.JSON(http.StatusOK, gin.H{"status": "成功登录"})
			} else {
				c.JSON(http.StatusUnauthorized, gin.H{"status": "未授权"})
			}
		} else {
			C.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		}
	})

	//HTML form (user=manu&password=123)
	router.POST("/loginForm", func(c *gin.Context) {
		var form Login
		if err := c.ShouldBind(&form); err == nil {
			if form.User == "manu" && form.Password == "123" {
				c.JSON(http.StatusOK, gin.H{"status": "成功登录"})
			} else {
				c.JSON(http.StatusUnauthorized, gin.H{"status": "未授权"})
			}
		} else {
			C.JSON(http.StatusBadRequest, gin.H{"error": err.Error})
		}
	})
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值