golang快速入门:类型系统

自定义数据类型

在go语言中,自定义类型就是使用type关键字定义新的类型,它可以是基本类型的别名,也可以是结构体、接口、函数组成的新类型,自定义类型可以帮助我们更好的抽象和封装数据,让代码更加的简洁,易读易维护。

在 Go 语言中,使用 type 关键字可以定义一个新的类型,语法如下:

bash 复制代码
type newType oldType

其中,NewType 是新类型的名称,OldType 可以是任何基本类型或现有类型的别名,通过这种方式可以创建一个新类型,使得这个新类型具有与原有类型不同的特性。

自定义数据类型是一种新的数据类型,与其基于的Go内置数据类型 是两种数据类型,无法用来进行 运算符计算 (算数运算符、逻辑运算符、关系运算符、位运算符等)。

less 复制代码
type MyInt int
 
var a MyInt = 10
var b int = 10
 
if a==b {
    fmt.Println("hello world")
}

程序报错

ini 复制代码
invalid opeartion: a == b (mismatched types Myint and int)

如果想要参与运算,必须进行转换。

scss 复制代码
if a==MyInt(b) {
    fmt.Println("hello world")
}

不仅可以定义基本数据类型,也可以定义函数类型

go 复制代码
type myFunc func(int) int

func sum10(num int) int {
    fmt.Println(num*10)
}
 
 
func main() {
    newFunc := myFunc(sum10)
}

定义成员方法

可以为自定义类型定义成员方法,下面基于 ​​​int​​​​ 设置了 ​​​​Code​​​ 类型(这是一个新类型,不是类型别名),在使用的时候也要通过 ​​​​Code​​​ 类型进行声明,不过本质上它仍然是一个整型数字,你可以把具体的数值看做是 ​​​​Code​​​ 类型的实例。

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())
}

同理,自定义函数类型也可以定义成员方法

go 复制代码
type myFunc func(int) int
 
func (mf myfunc) sum(a,b int) int {
    c := a + b
    return mf(c)
}

自定义函数类型结合接口、结构体使用,完成一些复杂的逻辑

go 复制代码
type sumable interface {
    sum(int, int) int
}
 
// myFunc继承sumable接口
type myFunc func(int) int
 
func (f myFunc) sum (a, b int) int {
    res := a + b
    return f(res)
}
 
func sum10(num int) int {
    return num * 10
}
 
func sum100(num int) int {
    return num * 100
}
 
// icansum结构体继承sumable接口
type icansum struct {
    name string
    res int
}
 
func (ics *icansum) sum(a, b int) int {
    ics.res = a + b
    return ics.res
}
 
// handler只要是继承了sumable接口的任何变量都行,我只需要你提供sum函数就好
func handlerSum(handler sumable, a, b int) int {
    res := handler.sum(a, b)
    fmt.Println(res)
    return res
}
 
func main() {
    newFunc1 := myFunc(sum10)
    newFunc2 := myFunc(sum100)
 
    handlerSum(newFunc1, 1, 1)    // 20
    handlerSum(newFunc2, 1, 1)    // 200
 
    ics := &icansum{"I can sum", 0}
    handlerSum(ics, 1, 1)         // 2
}

上面可以看出sum10 和 sum10(1) 之间的区别,前者是类型为 func(int) int 的变量,后者是函数调用。其次,newFunc1 := myFunc(sum10) 的意思是将 sum10 这个变量的类型转换成 myFunc 类型并赋值给 newFunc1,newFunc1 其实就是套了一个类型叫 myFunc 的马甲的 sum10 变量。那么对于第43行 handlerSum(newFunc1, 1, 1),接受了一个 newFunc1 这个函数变量传递进来,并调用了其 sum 函数即 newFunc1.sum(1, 1),该 sum 函数的定义是先进行 res:=a+b 的加法操作,然后调用 f(res) 即 newFunc1(res) 来返回。最终,newFunc1是什么?不就是被转换成了 myFunc 类型的 sum10 嘛,本质上就是一个函数变量,那么执行 newFunc1() 其实等同于执行 sum10()。所以运算过程是先进行了 a + b 的加法,然后针对这个加法的结果进行不同的干预,你可以自定义任何一个函数(比如本例中的 sum10、sum100),只要能套上 myFunc 这个马甲(可将该变量类型转换成 myFunc ),就能对 a + b 的结果进行自定义的干预。

类型别名

等于是给基础类型换一个别名。

go 复制代码
type intAlias = int

类型别名和自定义类型的区别

go 复制代码
type AliasInt = int
type MyInt int
  1. 不能绑定方法
scss 复制代码
//自定义类型可以定义成员方法
func (m MyInt) MyIntMethod() {

}

// AliasIntMethod 类型别名 不可以绑定方法
func (m AliasInt) AliasIntMethod() {

}
//别名绑定方法会报错 cannot define new methods on non-local type
  1. 打印类型还是原始类型
java 复制代码
var MyIntNum MyInt = 0
var AliasIntNum AliasInt = 0

//自定义类型不是原类型
fmt.Printf("%v, %T \n", MyIntNum, MyIntNum) //0 ,main.MyInt

//别名打印出来是原类型
fmt.Printf("%v %T \n", AliasIntNum, AliasIntNum)//0 ,int 
  1. 和原始类型比较,类型别名不用转换
csharp 复制代码
 var age int = 0
 //别名比较不用转换类型
fmt.Println(AliasIntNum == age)


//必须转换之后才能和原始类型比较
//invalid operation: MyIntNum == age (mismatched types MyInt and int)
fmt.Println(int(MyIntNum) == age) 

总结

  • 自定义数据类型是一种新的数据类型,与其基于的Go内置数据类型 是两种数据类型,无法用来进行 运算符计算 (算数运算符、逻辑运算符、关系运算符、位运算符等)
  • 类型别名 是其基于的Go内置数据类型的一种别名,二者是同一种数据类型,可以用来进行运算符计算
相关推荐
程序员爱钓鱼5 小时前
Go语言实战案例 — 工具开发篇:实现一个图片批量压缩工具
后端·google·go
ChinaRainbowSea7 小时前
7. LangChain4j + 记忆缓存详细说明
java·数据库·redis·后端·缓存·langchain·ai编程
舒一笑7 小时前
同步框架与底层消费机制解决方案梳理
后端·程序员
minh_coo7 小时前
Spring框架事件驱动架构核心注解之@EventListener
java·后端·spring·架构·intellij-idea
白初&8 小时前
SpringBoot后端基础案例
java·spring boot·后端
计算机学姐10 小时前
基于Python的旅游数据分析可视化系统【2026最新】
vue.js·后端·python·数据分析·django·flask·旅游
该用户已不存在11 小时前
你没有听说过的7个Windows开发必备工具
前端·windows·后端
David爱编程11 小时前
深入 Java synchronized 底层:字节码解析与 MonitorEnter 原理全揭秘
java·后端
KimLiu12 小时前
LCODER之Python:使用Django搭建服务端
后端·python·django
再学一点就睡12 小时前
双 Token 认证机制:从原理到实践的完整实现
前端·javascript·后端