我们可以在结构体的字段后面,添加一些对该字段的说明(元信息meta),程序通过反射解析这些信息并使用。
//注意外边是反引号
`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"))
}
重点:
blue gopher
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: "Crisp",
Password: "123456",
CreatedAt: time.Now(),
}
out, err := json.MarshalIndent(u, "", " ")
if err != nil {
log.Println(err)
os.Exit(1)
}
fmt.Println(string(out))
}
{
"name": "Crisp",
"password": "123456",
"createdAt": "2022-07-21T15:59:36.200572+08:00"
}
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: "C", LastName: "risp", 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
}
}
<person id="13">
<name>
<first>C</first>
<last>risp</last>
</name>
<age>18</age>
<Married>false</Married>
<City>北京</City>
<State>海淀</State>
<comment>注释.</comment>
</person>
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"`
}
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})
}
})
}
json
-由encoding/json包
使用,详细信息见json.Marshal()
xml
-由encoding/xml
包使用,详细信息见xml.Marshal()
bson
-由gobson
使用,详细信息在bson.Marshal()
;也由mongo-go
驱动程序,在bson package doct
中有详细说明protobuf-github.com/golang/protobuf/proto
使用者,文档中有详细说明yaml
-由gopkg.in/yaml.v2
包使用,详细信息见yaml.Marshal()
db
-被github.com/jmoiron/sqlx
包使用;也被github.com/go-gorp/gorp
包使用orm
-由github.com/astaxie/beego/orm
包使用,详见Models-Beego ORM
gorm
-使用gorm.io/gorm
,示例可以在他们的文档中找到valid
-由github.com/asaskevich/govalidator
包使用,示例可以在项目页面中找到datastore
-由appengine/datastore
(Google App Engine平台、Datastore服务)使用,详情见属性schema
-用于github.com/gorilla/schema
填充struct HTML表单值,在包文档中有详细说明asn
-由encoding/asn1
包使用,详细信息在asn1.Marshal()
和asn1.Unmarshal()
csv
-被github.com/gocarina/gocsv
包使用env
-被github.com/caarlos0/env
包使用