Skip to content

1. golang结构体

go语言没有面向对象的概念了,但是可以使用结构体来实现,面向对象编程的一些特性,例如:继承、组合等特性。

有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号、性能、性别、年龄、地址等属性。如果一个一个定义变量会比较繁琐,数据不便于管理。这时就可以引入结构体了

m_919a846007897080a41597f11bd5aa1e_r

1.1 go语言结构体的定义

结构体的定义和类型定义类似,只不过多了一个struct关键字,语法结构如下:

go
type struct_variable_type struct {
	member 类型;
	member 类型;
	...
	member 类型;
}
type struct_variable_type struct {
	member 类型;
	member 类型;
	...
	member 类型;
}

type:结构体定义关键字

struct_variable_type:结构体类型名称

struct:结构体定义关键字

member 类型: 成员定义

实例:

定义Person 的结构体

go
type Person struct {
	id int
	name string
	age int
	email string
}
type Person struct {
	id int
	name string
	age int
	email string
}

同类型的可以合并到一行用隔开

go
type Person struct {
	id,age int
	name,email string
}
type Person struct {
	id,age int
	name,email string
}

1.2 声明一个结构体变量

声明一个结构体变量和声明一个普通变量相同

go
package main

import "fmt"

//定义一个结构体
type Person struct {
	id    int
	name  string
	age   int
	email string
}

func main() {
	var tom Person
	fmt.Printf("tom: %v\n", tom)
}
package main

import "fmt"

//定义一个结构体
type Person struct {
	id    int
	name  string
	age   int
	email string
}

func main() {
	var tom Person
	fmt.Printf("tom: %v\n", tom)
}

结构体成员,在没有赋值之前都是零值

1.3访问结构体成员

可以使用点运算符(.),来访问结构体成员

go
package main

import "fmt"

type Person struct {
	id, age     int
	name, email string
}

func main() {
	var tom Person
	tom.id = 100
	tom.name = "tom"
	tom.age = 20
	tom.email = "xx@gmail.com"
	fmt.Println("--------访问所有成员")
	fmt.Printf("tom: %v\n", tom)
	fmt.Println("--------访问单个成员")
	fmt.Printf("tom.id: %v\n", tom.id)
}
package main

import "fmt"

type Person struct {
	id, age     int
	name, email string
}

func main() {
	var tom Person
	tom.id = 100
	tom.name = "tom"
	tom.age = 20
	tom.email = "xx@gmail.com"
	fmt.Println("--------访问所有成员")
	fmt.Printf("tom: %v\n", tom)
	fmt.Println("--------访问单个成员")
	fmt.Printf("tom.id: %v\n", tom.id)
}

1.4匿名结构体

如果结构体是临时使用,可以不用起名字,直接使用

go
func main() {
	var Cumster struct {
		id   int
		name string
	}
	Cumster.id = 100
	Cumster.name = "tom"
	fmt.Printf("Cumster: %v\n", Cumster)
}
func main() {
	var Cumster struct {
		id   int
		name string
	}
	Cumster.id = 100
	Cumster.name = "tom"
	fmt.Printf("Cumster: %v\n", Cumster)
}

2.结构体初始化

未初始化的结构体,成员都是零值 int 0 float 0.0 bool false string nil

go
type Person struct {
	id, age     int
	name, email string
}

func main() {
	var tom Person
	fmt.Printf("tom: %v\n", tom)
}
type Person struct {
	id, age     int
	name, email string
}

func main() {
	var tom Person
	fmt.Printf("tom: %v\n", tom)
}

2.1使用键值对

使用键值对对结构体初始化

go
type Person struct {
	id, age     int
	name, email string
}

func main() {
	kite := Person{
		id:    100,
		age:   19,
		name:  "tom",
		email: "xx@gmail.com",
	}
	fmt.Printf("kite: %v\n", kite)
}
type Person struct {
	id, age     int
	name, email string
}

func main() {
	kite := Person{
		id:    100,
		age:   19,
		name:  "tom",
		email: "xx@gmail.com",
	}
	fmt.Printf("kite: %v\n", kite)
}

2.2使用值的列表

使用值的列表初始化

go
type Person struct {
	id, age     int
	name, email string
}

func main() {
	kite := Person{
		100,
		19,
		"tom",
		"xx@gmail.com",
	}
	fmt.Printf("kite: %v\n", kite)
}
type Person struct {
	id, age     int
	name, email string
}

func main() {
	kite := Person{
		100,
		19,
		"tom",
		"xx@gmail.com",
	}
	fmt.Printf("kite: %v\n", kite)
}

[!NOTE]

1.必须初始化结构体的所有字段

2.初始值的填充顺序必须与字段在结构体中的声明顺序一致

3.该方式不能和键值初始化方式混用

2.3部分成员初始化

用不到的成员,可以不进行初始化

go
type Person struct {
	id, age     int
	name, email string
}

func main() {
    //使用键值对,短变量方式
	kite := Person{
		id:  100,
		age: 19,
	}
    //或者
    var tom Person
	tom = Person{
		id:  100,
		age: 20,
	}
    
	fmt.Printf("kite: %v\n", kite)
}
type Person struct {
	id, age     int
	name, email string
}

func main() {
    //使用键值对,短变量方式
	kite := Person{
		id:  100,
		age: 19,
	}
    //或者
    var tom Person
	tom = Person{
		id:  100,
		age: 20,
	}
    
	fmt.Printf("kite: %v\n", kite)
}

3.结构体指针

结构体指针和普通变量指针相同

3.1普通变量指针

go
package main

import "fmt"

func main() {
	var name string
	name = "tom"
	var p_name *string
	p_name = &name
	//取指针地址
	fmt.Println(p_name)

	//取指针地址值
	fmt.Printf("*p_name: %v\n", *p_name)
}
package main

import "fmt"

func main() {
	var name string
	name = "tom"
	var p_name *string
	p_name = &name
	//取指针地址
	fmt.Println(p_name)

	//取指针地址值
	fmt.Printf("*p_name: %v\n", *p_name)
}

3.2结构指针

go
func test2() {
	type Person struct {
		id   int
		name string
	}
	var tom = Person{
		1,
		"tom",
	}
	var p_person *Person
	p_person = &tom
	fmt.Printf("p_person: %p\n", p_person)
	fmt.Printf("p_person: %v\n", *p_person)
}
func test2() {
	type Person struct {
		id   int
		name string
	}
	var tom = Person{
		1,
		"tom",
	}
	var p_person *Person
	p_person = &tom
	fmt.Printf("p_person: %p\n", p_person)
	fmt.Printf("p_person: %v\n", *p_person)
}

3.3new创建结构体指针

还可以通过new关键字对结构体进行实例化,得到的是结构体的地址

go
func test3() {
	type Person struct {
		id   int
		name string
	}
	var p_person = new(Person)
	fmt.Printf("p_person: %p\n", p_person)
}
func test3() {
	type Person struct {
		id   int
		name string
	}
	var p_person = new(Person)
	fmt.Printf("p_person: %p\n", p_person)
}

3.4访问结构体成员

.进行访问

go
func test3() {
	type Person struct {
		id   int
		name string
	}
	var p_person = new(Person)
    //另一种方式,(*p_person).id=10 ,默认忽略星号
	p_person.id = 10
	p_person.name = "tom"
    //取值
	fmt.Printf("p_person: %v\n", *p_person)
}
func test3() {
	type Person struct {
		id   int
		name string
	}
	var p_person = new(Person)
    //另一种方式,(*p_person).id=10 ,默认忽略星号
	p_person.id = 10
	p_person.name = "tom"
    //取值
	fmt.Printf("p_person: %v\n", *p_person)
}

4.结构体作为函数参数

go结构体可以像普通函数一样,作为函数的参数,传递给函数,分两种情况

1.直接传递结构体,这是一个副本(拷贝),在函数内部不会改变外面结构体内容

2.传递结构体指针,这时在函数内部,能够改变外部结构体内容

4.1直接传递结构体

go
package main

import "fmt"

type Persons struct {
	id   int
	name string
}

func showPerson(per Persons) {
	per.id = 100
	per.name = "tom"
	fmt.Printf("per: %v\n", per)
}

func main() {
	han := Persons{
		101,
		"han",
	}
	fmt.Printf("han: %v\n", han)
	fmt.Println("---------------")
	showPerson(han)
	fmt.Printf("han: %v\n", han)
}

//
han: {101 han}
---------------
per: {100 tom}
han: {101 han}
package main

import "fmt"

type Persons struct {
	id   int
	name string
}

func showPerson(per Persons) {
	per.id = 100
	per.name = "tom"
	fmt.Printf("per: %v\n", per)
}

func main() {
	han := Persons{
		101,
		"han",
	}
	fmt.Printf("han: %v\n", han)
	fmt.Println("---------------")
	showPerson(han)
	fmt.Printf("han: %v\n", han)
}

//
han: {101 han}
---------------
per: {100 tom}
han: {101 han}

从运行结构看,函数内部改变了结构体内容,函数外面并没有被改变

4.2传递结构体指针

go
package main

import "fmt"

type Persons struct {
	id   int
	name string
}

func showPerson(per *Persons) {
	per.id = 100
	per.name = "tom"
	fmt.Printf("per: %v\n", per)
}

func main() {
	han := Persons{
		101,
		"han",
	}
	fmt.Printf("han: %v\n", han)
	fmt.Println("---------------")
	showPerson(han)
	fmt.Printf("han: %v\n", han)
}

//
han: {101 han}
---------------
per: &{100 tom}
han: {100 tom}
package main

import "fmt"

type Persons struct {
	id   int
	name string
}

func showPerson(per *Persons) {
	per.id = 100
	per.name = "tom"
	fmt.Printf("per: %v\n", per)
}

func main() {
	han := Persons{
		101,
		"han",
	}
	fmt.Printf("han: %v\n", han)
	fmt.Println("---------------")
	showPerson(han)
	fmt.Printf("han: %v\n", han)
}

//
han: {101 han}
---------------
per: &{100 tom}
han: {100 tom}

5.结构体嵌套

go语言没有面向对象编程思想,也没有继承关系,但是可以通过结构体嵌套来实现这种效果

一个人结构体,这个人还养了一个dog结构体

go
package main

import "fmt"

func main() {
	type Dog struct {
		name  string
		color string
		age   int
	}
	type Person struct {
		dog  Dog
		name string
		age  int
	}
	dog := Dog{
		"嘿嘿",
		"hei",
		10,
	}
	per := Person{
		dog,
		"tom",
		20,
	}
	fmt.Printf("per: %v\n", per)
    //单独访问dog
    fmt.Printf("per.dog.name: %v\n", per.dog.name)
}

//
per: {{嘿嘿 hei 10} tom 20}
package main

import "fmt"

func main() {
	type Dog struct {
		name  string
		color string
		age   int
	}
	type Person struct {
		dog  Dog
		name string
		age  int
	}
	dog := Dog{
		"嘿嘿",
		"hei",
		10,
	}
	per := Person{
		dog,
		"tom",
		20,
	}
	fmt.Printf("per: %v\n", per)
    //单独访问dog
    fmt.Printf("per.dog.name: %v\n", per.dog.name)
}

//
per: {{嘿嘿 hei 10} tom 20}

6.结构体标签

标签定义

Tag是结构体在编译阶段关联到成员的元信息字符串,在运行的时候通过反射的机制读取出来。

结构体标签由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。键值对之间使用一个空格分隔,具体的格式如下:

golang
`key1:"value1" key2:"value2" key3:"value3"...`  // 键值对用空格分隔
复制代码
`key1:"value1" key2:"value2" key3:"value3"...`  // 键值对用空格分隔
复制代码

key会指定反射的解析方式,如下: json(JSON标签) orm(Beego标签)、gorm(GORM标签)、bson(MongoDB标签)、form(表单标签)、binding(表单验证标签)

标签选项

golang
type Student struct {
    ID   int     `json:"-"`            // 该字段不进行序列化
    Name string  `json:name,omitempy`  // 如果为类型零值或空值,序列化时忽略该字段
    Age  int     `json:age,string`     // 指定类型,支持string、number、boolen
}
复制代码
type Student struct {
    ID   int     `json:"-"`            // 该字段不进行序列化
    Name string  `json:name,omitempy`  // 如果为类型零值或空值,序列化时忽略该字段
    Age  int     `json:age,string`     // 指定类型,支持string、number、boolen
}
复制代码

注:encoding/json官方文档

json标签

JSON说明

JSON数组可以用于编码Go语言的数组slice;由于JSON对象是一个字符串到值的映射,写成一系列的name:value对形式,因此JSON的对象类型可以用于编码Go语言的map结构体

将Go语言中结构体slice转为JSON的过程叫编组(marshaling),编组通过json.Marshal函数完成。在编码时,默认使用Go语言结构体的成员名字作为JSON的对象(通过reflect反射技术)。只有导出的结构体成员才会被编码。

如果在结构体slice编码成JSON的时候使用自定义的成员名,可以使用结构体成员Tag来实现。

JSON标签

golang
type User struct {
    ID   int `json:"id"`  // 编码后的字段名为 id
    Name string           // 编码后的字段名为 自定义成员名 Name
    age  int              // 未导出字段不能编码
}
复制代码
type User struct {
    ID   int `json:"id"`  // 编码后的字段名为 id
    Name string           // 编码后的字段名为 自定义成员名 Name
    age  int              // 未导出字段不能编码
}
复制代码

json为键名的标签对应的值用于控制encoding/json包的编码和解码的行为,并且encoding/...下面其它的包也遵循这个约定。

标签选项使用说明
-字段不进行序列化 例:json:"-"
omitempy类型零值或空值,序列化时忽略该字段 例:json:",omitempy" 字段名省略的话用结构体字段名
type重新指定字段类型 例:json:"age,string"

gorm标签

模型定义

模型是标准的 struct,由基本数据类型以及实现了 ScannerValuer 接口的自定义类型及其指针或别名组成。

GORM 定义一个 gorm.Model 结构体,如下所示:

golang
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}
复制代码
gorm`为键名的标签遵循GORM的解析规则,GORM支持如下tag,tag名大小写不敏感,建议使用`camelCase`风格,多个标签定义用`分号(;)分隔
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}
复制代码
gorm`为键名的标签遵循GORM的解析规则,GORM支持如下tag,tag名大小写不敏感,建议使用`camelCase`风格,多个标签定义用`分号(;)分隔

[知识点] Gorm建表时 AUTO_INCREMENT 不生效的问题

golang
// AUTO_INCREMENT 不生效
Id  uint64 `gorm:"column:id;primaryKey;type:bigint(20);autoIncrement;comment:'主键'"`
// AUTO_INCREMENT 不生效
Id  uint64 `gorm:"column:id;type:bigint(20);autoIncrement;comment:'主键'"`
// AUTO_INCREMENT 生效 gorm会自动根据字段类型设置数据库字段类型并设置为主键
Id  uint64 `gorm:"column:id;autoIncrement;comment:'主键'"` //写成AUTO_INCREMENT也可以
复制代码
// AUTO_INCREMENT 不生效
Id  uint64 `gorm:"column:id;primaryKey;type:bigint(20);autoIncrement;comment:'主键'"`
// AUTO_INCREMENT 不生效
Id  uint64 `gorm:"column:id;type:bigint(20);autoIncrement;comment:'主键'"`
// AUTO_INCREMENT 生效 gorm会自动根据字段类型设置数据库字段类型并设置为主键
Id  uint64 `gorm:"column:id;autoIncrement;comment:'主键'"` //写成AUTO_INCREMENT也可以
复制代码
标签选项使用说明
column指定 db 列名
type列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not nullsize, autoIncrement… 像 varbinary(8) 这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT
size指定列大小,例如:size:256
primaryKey指定列为主键
unique指定列为唯一
default指定列的默认值,字符串默认值用单引号,例:gorm:"default:'cn'"
precision指定列的精度
scale指定列大小
not null指定列为 NOT NULL
autoIncrement指定列为自动增长,不可与primaryKeytype同时使用否则不生效,看上面知识点部分
autoIncrementIncrement自动步长,控制连续记录之间的间隔
embedded嵌套字段
embeddedPrefix嵌入字段的列名前缀
autoCreateTime创建时追踪当前时间,对于 int 字段,它会追踪秒级时间戳,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoCreateTime:nano
autoUpdateTime创建/更新时追踪当前时间,对于 int 字段,它会追踪秒级时间戳,您可以使用 nano/milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli
index根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看 索引 获取详情
uniqueIndexindex 相同,但创建的是唯一索引
check创建检查约束,例如 check:age > 13,查看 约束 获取详情
<-设置字段写入的权限, <-:create 只创建、<-:update 只更新、<-:false 无写入权限、<- 创建和更新权限
->设置字段读的权限,->:false 无读权限
-忽略该字段,- 无读写权限
comment迁移时为字段添加注释

示例:

golang
// 内容模型
type Content struct {
    Model
    NewsId   uint64  `gorm:"column:news_id"`
    Content  string  `gorm:"column:content"`
}
复制代码
// 内容模型
type Content struct {
    Model
    NewsId   uint64  `gorm:"column:news_id"`
    Content  string  `gorm:"column:content"`
}
复制代码

知识点 自定义唯一索引

golang
// Go 版本:go1.16.6   Gorm 版本:v1.9.16
// 尝试用 uniqueIndex 创建不生效,有解决方法的同学欢迎评论区留言 普通索引是生效的
Email string `gorm:"column:email;type:varchar(50);uniqueIndex:uidx_email"` // 不生效
Email string `gorm:"column:email;type:varchar(50);index:idx_email"`        // 生效

// 创建唯一索引 建表时会创建名称为 email 的唯一索引
Email string `gorm:"column:email;type:varchar(50);unique"`
// 创建自定义名称 uidx_email 的唯一索引
Email string `gorm:"column:email;type:varchar(50)" sql:"unique_index:uidx_email"`
复制代码
// Go 版本:go1.16.6   Gorm 版本:v1.9.16
// 尝试用 uniqueIndex 创建不生效,有解决方法的同学欢迎评论区留言 普通索引是生效的
Email string `gorm:"column:email;type:varchar(50);uniqueIndex:uidx_email"` // 不生效
Email string `gorm:"column:email;type:varchar(50);index:idx_email"`        // 生效

// 创建唯一索引 建表时会创建名称为 email 的唯一索引
Email string `gorm:"column:email;type:varchar(50);unique"`
// 创建自定义名称 uidx_email 的唯一索引
Email string `gorm:"column:email;type:varchar(50)" sql:"unique_index:uidx_email"`
复制代码

知识点 自动更新时间

GORM约定使用CreatedAtUpdatedAt追踪创建/更新时间。如果定义了这种字段,且默认值为零值,GORM在创建、更新时会自动填充当前时间。要使用不同名称的字段,您可以配置autoCreateTimeautoUpdateTime标签,如果想要保存 UNIX(毫/纳)秒时间戳,而不是 time,只需简单地将 time.Time 修改为 int 即可,毫/纳秒参数可以看上面表格示例。

golang
// 时间自动创建和更新
type User struct { 
    // 自定义字段  使用时间戳填纳秒数充更新时间 
    Updated   int64 `gorm:"autoUpdateTime:nano"` 
    //自定义字段  使用时间戳毫秒数填充更新时间 
    Updated   int64 `gorm:"autoUpdateTime:milli"` 
    //自定义字段  使用时间戳秒数填充创建时间 
    Created   int64 `gorm:"autoCreateTime"` 
    // 默认创建时间字段  在创建时如果该字段值为零值,则使用当前时间填充 
    CreatedAt time.Time 
    // 默认更新时间字段  在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充 
    UpdatedAt int      
}
复制代码
// 时间自动创建和更新
type User struct { 
    // 自定义字段  使用时间戳填纳秒数充更新时间 
    Updated   int64 `gorm:"autoUpdateTime:nano"` 
    //自定义字段  使用时间戳毫秒数填充更新时间 
    Updated   int64 `gorm:"autoUpdateTime:milli"` 
    //自定义字段  使用时间戳秒数填充创建时间 
    Created   int64 `gorm:"autoCreateTime"` 
    // 默认创建时间字段  在创建时如果该字段值为零值,则使用当前时间填充 
    CreatedAt time.Time 
    // 默认更新时间字段  在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充 
    UpdatedAt int      
}
复制代码

注:GORM模型 官方文档

关联标签

GORM的关联类型有多重类型:belongs tohas onehas manymany to many具体结构体定义可参考问文档,关联模式使用的标签选项如下所示:

标签选项使用说明
foreignKey指定当前模型的列作为连接表的外键 例:gorm:"foreignKey:FieldId" 其中FieldID是外键字段名
references指定引用表的列名,其将被映射为连接表外键
polymorphic指定多态类型,比如模型名
polymorphicValue指定多态值、默认表名
many2many指定连接表表名
joinForeignKey指定连接表的外键列名,其将被映射到当前表
joinReferences指定连接表的外键列名,其将被映射到引用表
constraint关系约束,例如:OnUpdateOnDelete

示例:

golang
// 新闻模型
type News struct {
    Model
    Title   string   `gorm:"column:title;type:string;not null,default:''"`
    Content Content  `gorm:"foreignKey:NewsId" json:"content"` //指定外键
}
复制代码
// 新闻模型
type News struct {
    Model
    Title   string   `gorm:"column:title;type:string;not null,default:''"`
    Content Content  `gorm:"foreignKey:NewsId" json:"content"` //指定外键
}
复制代码

注:GORM关联模型 官方文档

form标签

Gin中提供了模型绑定,将表单数据和模型进行绑定,方便参数校验和使用。

模型绑定

golang
// 表单数据
type LoginForm struct {
    Email     string    `form:"emial"`    
    Password  string    `form:"password"`
}
// model 或 service 层Model
type Email struct {
    Email       string
    Password    string
}
复制代码
// 表单数据
type LoginForm struct {
    Email     string    `form:"emial"`    
    Password  string    `form:"password"`
}
// model 或 service 层Model
type Email struct {
    Email       string
    Password    string
}
复制代码

通过 form:"email" 对表单email数据进行绑定。然后通过Bind()、ShouldBind()等方法获取参数值。

golang
func EmailLogin (c *gin.Context) {
    var email LoginForm
    if err := c.ShouldBind(&email); err != nil {
        ...
    }
    // 获取表单数据局
    args := Email {
        Email:     email.Email,
        Password:  email.Password,
    }
    // 对参数进行后续使用
    ...
}
复制代码
func EmailLogin (c *gin.Context) {
    var email LoginForm
    if err := c.ShouldBind(&email); err != nil {
        ...
    }
    // 获取表单数据局
    args := Email {
        Email:     email.Email,
        Password:  email.Password,
    }
    // 对参数进行后续使用
    ...
}
复制代码

binding标签

Gin对于数据的校验使用的是 validator.v10 ,该包提供多种数据校验方法,通过binding:""标签来进行数据校验。

我们对上面的表单模型添加数据校验标签如下:

golang
type LoginForm struct {
    Email     string    `form:"emial" binding:"email"`    
    Password  string    `form:"password" binging:"required,min=6,max=10"`
}
复制代码
type LoginForm struct {
    Email     string    `form:"emial" binding:"email"`    
    Password  string    `form:"password" binging:"required,min=6,max=10"`
}
复制代码

特殊符号说明:

  • 逗号(,):分隔多个标签选项,逗号之间不能有空格,否则panic;
  • 横线(-):跳过该字段不做校验;
  • 竖线(|):使用多个选项,满足其中一个即可。

binding标签选项:

必需校验

标签选项使用说明示例
required表示该字段值必输设置,且不能为默认值binding:required
omitempty如果字段未设置,则忽略它binding:reqomitemptyuired

范围校验

范围验证: 切片、数组和map、字符串,验证其长度;数值,验证大小范围

标签选项使用说明示例
len参数值等于给定值binding:"len=8"等于8
ne不等于binding:"ne=8"不等于8
max最大值,小于等于参数值binding:"max=8"小于等于8
min最小值,大于等于参数值binding:"min=8"大于等于8
lte参数值小于等于给定值binding:"lte=8"小于等于8
gte参数值大于等于给定值binding:"gte=8"大于等于8
lt参数值小于给定值binding:"lt=8"小于8
gt参数值大于给定值binding:"gt=8"大于8
oneof参数值只能是枚举值中的一个,值必须是数值或字符串,以空格分隔,如果字符串中有空格,将字符串用单引号包围binding:"oneof=red green"

示例:

golang
type User struct {
    Name string `form:"name" binding:"required,min=1,max=10"`
    Age  unit8  `form:"age" binding:"lte=150,gte=0"`
    sex  string `form:"sex" binding:"oneof=male female"`
}
复制代码
type User struct {
    Name string `form:"name" binding:"required,min=1,max=10"`
    Age  unit8  `form:"age" binding:"lte=150,gte=0"`
    sex  string `form:"sex" binding:"oneof=male female"`
}
复制代码

注:文档地址

字符串校验

标签选项使用说明示例
contains参数值包含设置子串binding:"contains=tom"是否包含tom字符串
excludes参数值不包含设置子串binding:"excludes=tom"是否不包含tom字符串
startswith字符串前缀binding:"startswith=tom"是否以tom开头
endswith字符串前缀binding:"endswith=tom"是否以tom结尾

示例:

golang
type User struct {
    Name string `form:"name" binding:"required,contains=ac,endswith=ck"`
}
复制代码
type User struct {
    Name string `form:"name" binding:"required,contains=ac,endswith=ck"`
}
复制代码

注:文档地址

字段校验

标签选项使用说明
eqcsfield跨不同结构体字段相等,比如struct1 field1 是否等于struct2 field2
necsfield跨不同结构体字段不相等
eqfield同一结构体字段相等验证,例如:输入两次密码
nefield同一结构体字段不相等验证
gtefield大于等于同一结构体字段
ltefield小于等于同一结构体字段

示例:

golang
// 跨不同结构体字段相等
type Struct1 struct { 
    Field1 string `validate:eqcsfield=Struct2.Field2` 
    Struct2 struct { 
        Field2 string 
    } 
}
// 同一结构体字段相等验证
type Email struct { 
    Email  string `validate:"lte=4"` 
    Pwd    string `validate:"min=10"` 
    Pwd2   string `validate:"eqfield=Pwd"`
}
// 同一结构体字段验证不相等
type User struct { 
    Name     string `validate:"lte=4"` 
    Age      int `validate:"min=20"` 
    Password string `validate:"min=10,nefield=Name"`
}
复制代码
// 跨不同结构体字段相等
type Struct1 struct { 
    Field1 string `validate:eqcsfield=Struct2.Field2` 
    Struct2 struct { 
        Field2 string 
    } 
}
// 同一结构体字段相等验证
type Email struct { 
    Email  string `validate:"lte=4"` 
    Pwd    string `validate:"min=10"` 
    Pwd2   string `validate:"eqfield=Pwd"`
}
// 同一结构体字段验证不相等
type User struct { 
    Name     string `validate:"lte=4"` 
    Age      int `validate:"min=20"` 
    Password string `validate:"min=10,nefield=Name"`
}
复制代码

其他校验

标签选项使用说明示例
ip合法IP地址校验binding:"ip"
email合法邮箱校验binding:"email"
url合法的URLbinding:"url"
uri合法的URIbinding:"uri"
uuiduuid验证binding:"uuid"
datetime合法时间格式值校验binding:"datetime=2006-01-02"
jsonJSON数据验证validate:"json"
numeric数值验证 正则:^[-+]?[0-9]+(?:\\.[0-9]+)?$validate:"numeric"
number整数验证 正则:^[0-9]+$validate:"number"
alpha字母字符串验证 正则:^[a-zA-Z]+$validate:"alpha"
alphanum字母数字字符串验证 正则:^[a-zA-Z0-9]+$validate:"alphanum"
asciiAscii 字符验证validate:"ascii"

示例:

golang
type User struct { 
    Name     string  `validate:"required,min=1,max=10"` 
    Email    int     `validate:"required,email"`
    birthday string  `validate:"datetime=2006-01-02"`
    Pwd      string  `validate:"required,alphanum"`
    Score    srring  `validate:"numeric"`
}
复制代码
type User struct { 
    Name     string  `validate:"required,min=1,max=10"` 
    Email    int     `validate:"required,email"`
    birthday string  `validate:"datetime=2006-01-02"`
    Pwd      string  `validate:"required,alphanum"`
    Score    srring  `validate:"numeric"`
}
复制代码

注:文档地址

ini标签

在使用go-ini库操作.ini配置文件的时候,如果需要将配置文件字段映射到结构体变量,如果键名与字段名不相同,那么需要在结构标签中指定对应的键名。标准库encoding/jsonencoding/xml解析时可以将键名app_name对应到字段名AppName,而go-ini库不可以,所以需要在结构体标签指定对应键名。

ini
## 配置文件 cnf.ini
app_name  = awesome web
log_level = DEBUG
复制代码
// 配置文件映射 结构体
type Config struct {
  AppName   string `ini:"app_name"`  // ini标签指定下键名
  LogLevel  string `ini:"log_level"`
}
## 配置文件 cnf.ini
app_name  = awesome web
log_level = DEBUG
复制代码
// 配置文件映射 结构体
type Config struct {
  AppName   string `ini:"app_name"`  // ini标签指定下键名
  LogLevel  string `ini:"log_level"`
}