【Go】结构体、自定义类型与接口

🌈 个人主页: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

  1. 这个不写 json 标签转换为 json 的话,字段名就是属性的名字
  2. 小写的属性也不会转换

如果再转 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) // 必须要转成原始类型才能判断
}

🦋 类型别名

和自定义类型很像,但是有一些地方和自定义类型有很大差异

  1. 不能绑定方法
  2. 打印类型还是原始类型
  3. 和原始类型比较,类型别名不用转换
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】结构体、自定义类型与接口 的理解, 觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~ 😉

相关推荐
枫叶丹41 小时前
【Qt开发】Qt窗口(四) -> QDockWidget浮动窗口
c语言·开发语言·c++·qt·开源
星释1 小时前
Rust 练习册 101:字符串序列切片的艺术
开发语言·后端·rust
r***R2891 小时前
Spring Boot3.3.X整合Mybatis-Plus
spring boot·后端·mybatis
q_19132846951 小时前
基于SpringBoot+uniapp+vue.js的货物配送系统
java·vue.js·spring boot·后端·mysql·uni-app·毕业设计
v***55341 小时前
什么是Spring Boot 应用开发?
java·spring boot·后端
2509_940880221 小时前
Spring Cloud GateWay搭建
android·前端·后端
k***92161 小时前
SpringBoot集成MQTT客户端
java·spring boot·后端
6***83051 小时前
VMware虚拟机配置桥接网络
开发语言·网络·php
de_furina1 小时前
[C++]string类的使用和模拟实现
开发语言·c++·gitee