网站系统修改,做电子商务网站的总结,seo刷网站,校园网认证登录入口作者简介#xff1a; 高科#xff0c;先后在 IBM PlatformComputing从事网格计算#xff0c;淘米网#xff0c;网易从事游戏服务器开发#xff0c;拥有丰富的C#xff0c;go等语言开发经验#xff0c;mysql#xff0c;mongo#xff0c;redis等数据库#xff0c;设计模…作者简介 高科先后在 IBM PlatformComputing从事网格计算淘米网网易从事游戏服务器开发拥有丰富的Cgo等语言开发经验mysqlmongoredis等数据库设计模式和网络库开发经验对战棋类回合制moba类页游手游有丰富的架构设计和开发经验。 谢谢你的关注
------------------------------------------------------------------------------------------------------------------------------- 在Go语言中没有类的概念但可以使用struct来定义自定义类型。struct是一种可以包含多个不同类型字段的复合数据类型。可以将它看作是一个数据结构其中每个字段都有自己的类型和值。 本文相当于go的数据类型的一部分,在分享struct之前我有必要解释下类型别名和自定义类型的区别
类型别名和自定义类型
自定义类型
在Go语言中有一些基本的数据类型如string、整型、浮点型、布尔等数据类型Go语言中可以使用type关键字来定义自定义类型。
自定义类型是定义了一个全新的类型。我们可以基于内置的基本类型定义也可以通过struct定义。例如
type RANKTYPE int32const (RANKTYPE_GLOBAL_DECORATE RANKTYPE 0 //全服装扮排名RANKTYPE_PRIVANCE_DECORATE RANKTYPE 1 //省级装扮排名RANKTYPE_FRIEND_DECORATE RANKTYPE 2 //好友的装扮排名RANKTYPE_SEASON_SCORE RANKTYPE 3 //赛季积分排行榜RANKTYPE_LOCAL_SCORE RANKTYPE 4 //本地积分排行RANKTYPE_BIGSEASON_SCORE RANKTYPE 5 //赛季积分世界排行榜RANKTYPE_ACTIVITY_SCORE RANKTYPE 6 //活动积分排行RANKTYPE_CROSSSEASON_SCORE RANKTYPE 7 //跨服美食积分排行 暂时不用,RANKTYPE_SCENCEPROCESS_SCORE RANKTYPE 8 //场景进度跨服排行RANKTYPE_DECORATE_SCORE RANKTYPE 9 //场景进度跨服排行RANKTYPE_HANDBOOK_SCORE RANKTYPE 10 //场景图鉴跨服排行RANKTYPE_COSTUMDESIGNVOTE_SCORE RANKTYPE 11 //装扮设计投票排行RANKTYPE_PANDFISH_SCORE RANKTYPE 12 //钓鱼 池塘鱼的排行记录RANKTYPE_SCTREAMFISH_SCORE RANKTYPE 13 //钓鱼 溪流鱼的排行记录RANKTYPE_MARINEFISH_SCORE RANKTYPE 14 // 钓鱼 海洋鱼的排行记录RANKTYPE_SCOREFIISHING_SCORE RANKTYPE 15 //钓鱼积分的排行记录
)
通过type关键字的定义RANKTYPE就是一种新的类型它具有int的特性。
类型别名
类型别名是Go1.9版本添加的新功能。
类型别名规定TypeAlias只是Type的别名本质上TypeAlias与Type是同一个类型。就像一个孩子小时候有小名、乳名上学后用学名英语老师又会给他起英文名但这些名字都指的是他本人。 type TypeAlias Type
我们之前见过的rune和byte就是类型别名他们的定义如下 type byte uint8type rune int32
类型定义和类型别名的区别
类型别名与类型定义表面上看只有一个等号的差异我们通过下面的这段代码来理解它们之间的区别。
package mainimport fmt
//类型定义
type NewInt int//类型别名
type MyInt intfunc main() {var a NewIntvar b MyIntfmt.Printf(type of a:%T\n, a) fmt.Printf(type of b:%T\n, b)
}
输出 结果显示a的类型是main.NewInt表示main包下定义的NewInt类型。b的类型是int。MyInt类型只会在代码中存在编译完成时并不会有MyInt类型。
struct结构体
结构体的定义
使用type和struct关键字来定义结构体具体代码格式如下 type 类型名 struct {字段名 字段类型字段名 字段类型…}
其中 1.类型名标识自定义结构体的名称在同一个包内不能重复。2.字段名表示结构体字段名。结构体中的字段名必须唯一。3.字段类型表示结构体字段的具体类型。
举个例子我们定义一个游戏玩家的Player结构体代码如下 type Player struct {playerid stringname stringlevel intexp intlogintime int64registertime int64coin int32gem int32}
我们可以把具有相同数据类型的比如name和playerid的所有键都在一行上分组和定义 type Player struct {playerid,name stringlevel ,exp int logintime,registertime int64coin ,gem int32}
这样我们就拥有了一个Player的自定义类型它有playerid,name等字段。
结构体的tags
结构体的tags是附加到字段中的元数据的小片段为struct使用该结构的其他 Go 代码提供指令。
例如这里是名为的自定义类型Employee可以注释为
type Employee struct {FirstName string json: first_name LastName string json: last_nameEmployeeID string json: employee_idSalary float64 json: salary
}
然后Go 代码能够检查这些结构并提取分配给它请求的特定键的值。如果没有其他代码检查结构标记则结构标记不会影响代码的操作。
如果我们正在读取YAML或JSON文件那么我们可以注释struct这样的内容
type Employee struct {FirstName string yaml: first_name LastName string yaml: last_nameEmployeeID string yaml: employee_idSalary float64 yaml: salary
}
type Manager struct {ManagerFirstName string json: manager_first_name ManagerLastName string json: manager_last_nameManagerEmployeeID string json: manager_employee_idManagerSalary float64 json: manager_salary
}
下面的代码读取文件YAML并将文件中的值分配YAML给变量
var mgr Manager
f, err : os.Open(manager_list.json)if err ! nil {log.Fatalf(os.Open() failed with %s\n, err)}defer func(f *os.File) {err : f.Close()if err ! nil {
}}(f)
mrgObj : yaml.NewDecoder(f)err mrgObj.Decode(mgr)if err ! nil {log.Fatalf(dec.Decode() failed with %s\n, err)}
fmt.Println(%s %s employ_id is %s, mgr.FirstName, mgr.LastName, mgr.EmployeeID)
标准库中的JSON 编码器使用结构标记作为注释向编码器指示您希望如何命名JSON输出中的字段。这些JSON编码和解码机制可以在encoding/json 包中找到。
现在假设您有一个空的 JSON 字段您想要消除它那么您可以使用它omitempty如果JSON对象没有该键的值则不会填充和跳过它 type Manager struct {ManagerFirstName string json: manager_first_name ManagerLastName string json: manager_last_nameManagerEmployeeID string json: manager_employee_idManagerSalary float64 json: manager_salary,omitempty
} 如果你想忽略某些字段那么你可以使用-in tags它将被忽略 type Manager struct {ManagerFirstName string json: manager_first_name ManagerLastName string json: manager_last_nameManagerEmployeeID string json: manager_employee_idManagerSalary float64 json: -
} 如果您想更深入地访问tags那么您可以使用允许运行时反射的反射包
使用它tag可以让您更轻松地导航存储数据及其表示形式。您可以使用go-playground/validator它提供了更多有关tags.有些能力就像
字段之间的比较领域之间的调节管理字段之间的依赖关系等等……
例如下面的示例展示了如何使用go-playground/validator来验证字段而无需编写任何额外的代码。 type Manager struct {ManagerFirstName string json:manager_first_name validate:required ManagerLastName string json:manager_last_name validate:required_ifManagerFirstNameManagerEmployeeID string json:manager_employee_id validate:required, gte1000,lt10000ManagerSalary float64 json: manager_salary,omitempty
} 在上面的例子中我能够validate遵循
ManagerFirstName是required字段ManagerLastNameisrequired_if字段ManagerFirstName已提供ManagerEmployeeID是required字段并且不能小于1000
因此我们可以使用go-playground/validator而不是为某些基本和条件验证编写数据验证代码因为它们具有相同的内置逻辑完全基于tags 只有当结构体实例化时才会真正地分配
结构体实例化
只有当结构体实例化时才会真正地分配内存。也就是必须实例化后才能使用结构体的字段。
结构体本身也是一种类型我们可以像声明内置类型一样使用var关键字声明结构体类型。 var 结构体实例 结构体类型 基本实例化
我们通过var p1 Player的方式来实例化一个Player结构体并通过.操作来访问或者修改其成员变量
package mainimport (fmt
)
type Player struct {Playerid string json: playerid Name string json: name Level int json: level Exp int json: exp Logintime int64 json: logintime Registertime int64 json: registertime Coin int32 json: coin Gem int32 json: gem
} func main() {var p1 Playerp1.Playerid 12222222p1.Name 高科p1.Level 100fmt.Printf(p1%v\n, p1) //p1{12222222 高科 100 0 0 0 0 0}fmt.Printf(p1%#v\n, p1) //p1main.Player{Playerid:12222222, Name:高科, Level:100, Exp:0, Logintime:0, Registertime:0, Coin:0, Gem:0}
}
或者你可以直接在实例化的同时进行初始化操作所以下面的初始化方式都可以 var p1 Player{playerid:12222222,Name:高科,Level: 100, Exp:20, Logintime: 1711296000, Registertime:1701296000, Coin:100000, Gem:999999} p2 : Player{playerid:12222223,Name:高科2,Level: 100, Exp:20, Logintime: 1711296000, Registertime:1701296000, Coin:100000, Gem:999999} 匿名结构体
在定义一些临时数据结构等场景下还可以使用匿名结构体。
package mainimport (fmt
)
func main() {var p1 struct{playerid string json: playerid Name string json: name Level int json: level Exp int json: exp Logintime int64 json: logintime Registertime int64 json: registertime Coin int32 json: coin Gem int32 json: gem } p1.playerid 12222222p1.Name 高科p1.Level 100fmt.Printf(p1%v\n, p1) //p1{12222222 高科 100 0 0 0 0 0}fmt.Printf(p1%#v\n, p1) //p1main.Player{Playerid:12222222, Name:高科, Level:100, Exp:0, Logintime:0, Registertime:0, Coin:0, Gem:0}
} 创建指针类型结构体
我们还可以通过使用new关键字或者对结构体进行实例化得到的是结构体的地址。 格式如下 var 变量名 new(struct类型) package mainimport (fmt
)
type Player struct {playerid string json: playerid Name string json: name Level int json: level Exp int json: exp Logintime int64 json: logintime Registertime int64 json: registertime Coin int32 json: coin Gem int32 json: gem
} func main() {var p1 new(Player) var p2 Player{} fmt.Printf(p1%v ,p2%v \n, p1,p2) //p1{ 0 0 0 0 0 0} fmt.Printf(p1%#v ,p2%#v \n, p1,p2) //p1main.Player{playerid:, Name:, Level:0, Exp:0, Logintime:0, Registertime:0, Coin:0, Gem:0}
}