golang快速入门:类型系统和别名
  UQv5SPUvgZGD 2023年12月22日 15 0

golang快速入门:类型系统和别名_自定义类型


自定义数据类型

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

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

type newType oldType

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

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

type MyInt int
 
var a MyInt = 10
var b int = 10
 
if a==b {
    fmt.Println("hello world")
}

程序报错

invalid opeartion: a == b (mismatched types Myint and int)

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

if a==MyInt(b) {
    fmt.Println("hello world")
}

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

type myFunc func(int) int

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

定义成员方法

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

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

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

type myFunc func(int) int
 
func (mf myfunc) sum(a,b int) int {
    c := a + b
    return mf(c)
}

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

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 的结果进行自定义的干预。

类型别名

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

//格式:type 自定义类型名 = Go内置数据类型
type intAlias = int

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

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

}

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

}
//别名绑定方法会报错 cannot define new methods on non-local type
  1. 打印类型还是原始类型
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. 和原始类型比较,类型别名不用转换
 var age int = 0
 //别名比较不用转换类型
fmt.Println(AliasIntNum == age)


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

总结

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


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月22日 0

暂无评论

UQv5SPUvgZGD