
🌈 个人主页:Zfox_
🔥 系列专栏:Go

目录
- [一:🔥 结构体](#一:🔥 结构体)
-
- [🦋 继承](#🦋 继承)
- [🦋 结构体指针](#🦋 结构体指针)
- [🦋 结构体 tag](#🦋 结构体 tag)
- [🦋 json tag](#🦋 json tag)
- [二:🔥 自定义数据类型](#二:🔥 自定义数据类型)
-
- [🦋 自定义类型](#🦋 自定义类型)
- [🦋 类型别名](#🦋 类型别名)
- [三:🔥 接口](#三:🔥 接口)
-
- [🦋 类型断言](#🦋 类型断言)
- [🦋 空接口](#🦋 空接口)
- [四:🔥 共勉](#四:🔥 共勉)
一:🔥 结构体
结构体定义
go
type 结构体名称 struct{
名称 类型//成员或属性
}
go
package main
import "fmt"
// Student 定义结构体
type Student struct {
Name string
Age int
}
// PrintInfo 给机构体绑定一个方法
func (s Student) PrintInfo() {
fmt.Printf("name:%s age:%d\n", s.Name, s.Age)
}
func main() {
s := Student{
Name: "枫枫",
Age: 21,
}
s.Name = "枫枫知道" // 修改值
s.PrintInfo()
}
🦋 继承
go
package main
import "fmt"
type People struct {
Time string
}
func (p People) Info() {
fmt.Println("people ", p.Time)
}
// Student 定义结构体
type Student struct {
People
Name string
Age int
}
// PrintInfo 给机构体绑定一个方法
func (s Student) PrintInfo() {
fmt.Printf("name:%s age:%d\n", s.Name, s.Age)
}
func main() {
p := People{
Time: "2023-11-15 14:51",
}
s := Student{
People: p,
Name: "枫枫",
Age: 21,
}
s.Name = "枫枫知道" // 修改值
s.PrintInfo()
s.Info() // 可以调用父结构体的方法
fmt.Println(s.People.Time) // 调用父结构体的属性
fmt.Println(s.Time) // 也可以这样
}
🦋 结构体指针
之前我们了解了值传递和引用传递,如果我想在函数里面或者方法里面修改结构体里面的属性
只能使用结构体指针或者指针方法
go
package main
import "fmt"
type Student struct {
Name string
Age int
}
func SetAge(info Student, age int) {
info.Age = age
}
func SetAge1(info *Student, age int) {
info.Age = age
}
func main() {
s := Student{
Name: "枫枫",
Age: 21,
}
fmt.Println(s.Age)
SetAge(s, 18)
fmt.Println(s.Age)
SetAge1(&s, 17)
fmt.Println(s.Age)
}
go
package main
import "fmt"
type Student struct {
Name string
Age int
}
func (s Student) SetAge(age int) {
s.Age = age
}
func (s *Student) SetAge1(age int) {
s.Age = age
}
func main() {
s := Student{
Name: "枫枫",
Age: 21,
}
s.SetAge(18)
fmt.Println(s.Age)
s.SetAge1(18)
fmt.Println(s.Age)
}
🦋 结构体 tag
go
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
s := Student{
Name: "枫枫",
Age: 21,
}
byteData, _ := json.Marshal(s)
fmt.Println(string(byteData))
}
🦋 json tag
- 这个不写 json 标签转换为 json 的话,字段名就是属性的名字
- 小写的属性也不会转换
空
如果再转 json 的时候,我不希望某个字段被转出来,我可以写一个 -
go
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
Name string `json:"name"`
Age int `json:"age"`
Password string `json:"-"`
}
func main() {
s := Student{
Name: "枫枫",
Age: 21,
Password: "123456",
}
byteData, _ := json.Marshal(s)
fmt.Println(string(byteData)) // {"name":"枫枫","age":21}
}
omitempty
空值省略
go
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
func main() {
s := Student{
Name: "枫枫",
Age: 0, // 空值会被省略
}
byteData, _ := json.Marshal(s)
fmt.Println(string(byteData)) // {"name":"枫枫"}
}
二:🔥 自定义数据类型
在 Go 语言中,自定义类型指的是使用 type 关键字定义的新类型,它可以是基本类型的别名,也可以是结构体、函数等组合而成的新类型。自定义类型可以帮助我们更好地抽象和封装数据,让代码更加易读、易懂、易维护
🦋 自定义类型
结构体就是自定义类型中的一种
除此之外我们使用自定义类型,还可以让代码组合更加规范
例如,响应给客户端的想要码,我给他一个自定义类型
go
package main
import "fmt"
type Code int
const (
SuccessCode Code = 0
ValidCode Code = 7 // 校验失败的错误
ServiceErrCode Code = 8 // 服务错误
)
func (c Code) GetMsg() string {
// 可能会有更加响应码返回不同消息内容的要求,我们在这个函数里面去实现即可
// 可能还会有国际化操作
return "成功"
}
func main() {
fmt.Println(SuccessCode.GetMsg())
var i int
fmt.Println(int(SuccessCode) == i) // 必须要转成原始类型才能判断
}
🦋 类型别名
和自定义类型很像,但是有一些地方和自定义类型有很大差异
- 不能绑定方法
- 打印类型还是原始类型
- 和原始类型比较,类型别名不用转换
go
package main
import "fmt"
type AliasCode = int
type MyCode int
const (
SuccessCode MyCode = 0
SuccessAliasCode AliasCode = 0
)
// MyCodeMethod 自定义类型可以绑定自定义方法
func (m MyCode) MyCodeMethod() {
}
// MyAliasCodeMethod 类型别名 不可以绑定方法
func (m AliasCode) MyAliasCodeMethod() {
}
func main() {
// 类型别名,打印它的类型还是原始类型
fmt.Printf("%T %T \n", SuccessCode, SuccessAliasCode) // main.MyCode int
// 可以直接和原始类型比较
var i int
fmt.Println(SuccessAliasCode == i)
fmt.Println(int(SuccessCode) == i) // 必须转换之后才能和原始类型比较
}
三:🔥 接口
接口是一组仅包含方法名、参数、返回值的未具体实现的方法的集合
go
package main
import "fmt"
// Animal 定义一个animal的接口,它有唱,跳,rap的方法
type Animal interface {
sing()
jump()
rap()
}
// Chicken 需要全部实现这些接口
type Chicken struct {
Name string
}
func (c Chicken) sing() {
fmt.Println("chicken 唱")
}
func (c Chicken) jump() {
fmt.Println("chicken 跳")
}
func (c Chicken) rap() {
fmt.Println("chicken rap")
}
// 全部实现完之后,chicken就不再是一只普通的鸡了
func main() {
var animal Animal
animal = Chicken{"ik"}
animal.sing()
animal.jump()
animal.rap()
}
接口本身不能绑定方法
接口是值类型,保存的是:值+原始类型
go
package main
import "fmt"
// Animal 定义一个animal的接口,它有唱,跳,rap的方法
type Animal interface {
sing()
jump()
rap()
}
// Chicken 需要全部实现这些接口
type Chicken struct {
Name string
}
func (c Chicken) sing() {
fmt.Println("chicken 唱")
}
func (c Chicken) jump() {
fmt.Println("chicken 跳")
}
func (c Chicken) rap() {
fmt.Println("chicken rap")
}
// Cat 需要全部实现这些接口
type Cat struct {
Name string
}
func (c Cat) sing() {
fmt.Println("cat 唱")
}
func (c Cat) jump() {
fmt.Println("cat 跳")
}
func (c Cat) rap() {
fmt.Println("cat rap")
}
func sing(obj Animal) {
obj.sing()
}
// 全部实现完之后,chicken就不再是一只普通的鸡了
func main() {
chicken := Chicken{"ik"}
cat := Cat{"阿狸"}
sing(chicken)
sing(cat)
}
实现接口:
一个类型实现了接口的所有方法
即实现了该接口
🦋 类型断言
在使用接口的时候,我还是希望知道此是的具体类型是什么,我们可以通过断言来获取
go
func sing(obj Animal) {
// 通过断言来获取此时的具体类型
switch obj.(type) {
case Chicken:
fmt.Println("鸡")
case Cat:
fmt.Println("猫")
}
obj.sing()
}
或者是断言某个类型
go
func sing(obj Animal) {
c, ok := obj.(Chicken) // 两个参数 断言之后的类型 是否是对应类型
fmt.Println(c, ok)
d := obj.(Cat) // 一个参数 就是断言之后的类型,注意,类型不对是要报错的 main.Animal is main.Chicken, not main.Cat
fmt.Println(d)
}
🦋 空接口
空接口可以接受任何类型
换一种,任何类型都实现了空接口的定义
go
type EmptyInterfase interface {
}
// interface
func Print(val any) {
fmt.Println(val)
}
四:🔥 共勉
😋 以上就是我对 【Go】结构体、自定义类型与接口 的理解, 觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~ 😉
