golang-type关键字

type 关键字

Type关键字在Go语言中作用很重要,他主要用来实现两个功能:

【自定义类型】
自定义类型底层是一种类型,但是不会拥有底层类型的方法。
自定义类型与底层类型相比是一种新类型,二者之间需要显式类型转换。
//语法
type 自定义类型 底层类型

【类型别名】
类型别名就是为原类型取个新名字,完整拥有原类型的方法。
//语法
type 类型别名 = 原类型

自定义类型

基本语法

type 自定义类型 底层类型;

声明自定义类型并赋值

声明自定义类型

在Go 语言中,基础类型有下面几种:

bool byte complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr

使用 type 关键字可以定义我们自己的类型,如我们可以使用type定义一个新的结构体,也可以基于一个已经存在的类型来定义新类型,然后就可以在我们的代码中使用新的类型名字,这称为自定义类型,如:

type IZ int

这里IZ就是完全是一种新类型,然后我们可以使用下面的方式声明变量:

var a IZ =5

这里我们可以看到 int 是变量 a 的底层类型,这也使得它们之间存在相互转换的可能。

理解

在已有的类型上映射出一个新类型,该类型可以存储与底层变量一样的值。

1.自定义类型不拥有原类型的方法,只是用来存储原类型一样的值。

好比于我们不满足golang之前对整数的处理方法,于是我们定义一种新类型来存储整数,然后重新给他加方法。

type IZ int 中,IZ 就是基于int 类型构建的新类型,这称为自定义类型。然后就可以使用 IZ 来操作 int 类型的数据。

多个自定义类型声明

如果我们有多个类型需要定义,可以使用因式分解关键字的方式,例如:

type (
   IZ int
   FZ float64
   STR string
)

显式转换

自定义类型与原类型已经分道扬镳了,虽然变量的形式长的一样,但是他们属于不同的类型,拥有着不同的方法。

就好比亚洲人,日本人和韩国人虽然都属于亚洲人,但是实际上属于不同国家,如果要调整国籍需要显式转换。

5是整数,int和我们的自定义类型IZ都是整数,但实际上是不同类型,需要也需要显式转换。

举例

type IZ int
var a IZ = 5
//虽然a的值是5,也是整数,但是他已经属于IZ,
//如果我们要将他给int,就需要显式转换
b := int(a) 

官方解释

每个值在经过编译后都必须属于某个类型(编译器必须能够推断出所有值的类型),因为 Go 语言是一种静态类型语言。

在必要以及可行的情况下,一个类型的值可以被转换成另一种类型的值。

由于 Go 语言不存在隐式类型转换,因此所有的转换都必须显式说明,就像调用一个函数一样(类型在这里的作用可以看作是一种函数):

//强制转换的语法
valueOfTypeB = typeB(valueOfTypeA)
//中文
类型 B 的值 = 类型 B(类型 A 的值)

方法验证

自定义类型不具备原类型的方法。

package struct_knowledge

import "fmt"

//基础类型结构体
type Age struct{
	age int
} 
//自定义类型
type Myage Age

//我们给Age类型添加一个方法
func (a Age) IsAdult(){
	if(a.age>=18){
		fmt.Println("已经成年")
	}else{
		fmt.Println("未成年")
	}
}
//验证自定义类型是否有底层类型的方法
func CustomerType(){
	var age1 = Age{
		age:19,
	}

	var age2 = Myage{
		age:20,
	}

	age1.IsAdult()

	/*
		报错:
		age2.IsAdult undefined
		type Myage has no field or method IsAdult
	*/
	// age2.IsAdult()
}

通过Type 关键字在原有类型基础上构造出一个新类型,我们需要针对新类型来重新创建新方法。

自定义类型存在意义

我们不能给私有类型添加方法,例如

bool byte complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr

他们都是小写开头,也就是golang的本地私有类型,如果我们向给他们添加方法就会报错,例如:

golang的本地私有类型,指的是上述这些golang自带类型。我们自己定义的私有类型不算。

//给golang的私有类型添加方法会报错
// cannot define new methods on non-local type int
func (a int) IsOdd()bool{
	if(a%2==0){
		fmt.Println("a是偶数")
		return false
	}else{
		fmt.Println("a是奇数")
		return true
	}
}

报错信息

 cannot define new methods on non-local type int

所以我们想给原类型添加新方法只能用自定义类型来映射底层类型。

后续说到的类型别名,本质上是给底层类型重命名,所以无法解决这个问题。

类型别名

基本语法

type 类型别名 = 原类型名;

别名类型和原类型,这两个类型可以视为完全一致,能交换使用。

我们把type 类型别名定义的新类型叫做别名类型。

举例

package type_knowledge

import "fmt"

type Myint = int 

func GetInt(){
	var a Myint = 20
	var b int
    //不需要类型转换,因为二者本质上是同一类型
	b = a 
	fmt.Printf("b的值为%d\n",b)
}

理解

就好比于,你在中国叫张三,去了国外取了个英文名Sam,本质上还是一个人。

方法验证

别名类型本质上还是原类型,所以拥有原类型的一切方法与性质。

本地类型不允许添加方法

type Myint = int
//给golang的私有类型添加方法会报错
// cannot define new methods on non-local type int
func (a Myint) IsOdd()bool{
	if(a%2==0){
		fmt.Println("a是偶数")
		return false
	}else{
		fmt.Println("a是奇数")
		return true
	}
}

从报错信息可知,golang是凭借原类型来识别别名类型的。

测试方法

package type_knowledge

import "fmt"

type Book struct{
	price int
}

type MyBook = Book 

func (a Book) IsCheap() bool{
	if(a.price>=20){
		fmt.Println("The book is expensive")
		return false
	}else{
		fmt.Println("The book is cheap")
		return true
	}
}

func OtherNameType(){
	book1 := Book{
		price: 25,
	}
	book2 := MyBook{
		price: 30,
	}

	book1.IsCheap()
	book2.IsCheap()
}

别名类型拥有原类型的所有方法。

注意事项

由于别名类型本质上就是原类型,所以我们给别名类型添加方法也就是在给原类型添加方法。

别名类型存在的意义

字符在计算机中是用数字存储的,所以没有必要再创造一种新类型,所以golang存储字符的类型的底层源码为:

type byte = int8
type rune = int32
Go 语言有 25 个关键字,下面对这些关键字进行全面解析: #### 包管理 - **`package`**:用于定义代码所属的包,每个 Go 源文件都必须在文件开头声明所属的包。 ```go package main ``` - **`import`**:用于导入其他包,以便在当前代码中使用这些包提供的功能。 ```go import "fmt" ``` #### 函数定义与调用 - **`func`**:用于定义函数。 ```go func add(a, b int) int { return a + b } ``` - **`defer`**:用于延迟执行一个函数,通常用于资源的释放,无论函数是正常返回还是发生异常,`defer` 语句都会在函数结束前执行。 ```go func main() { defer fmt.Println("This will print last") fmt.Println("This will print first") } ``` - **`go`**:用于开启一个新的 goroutine,实现并发编程。 ```go func printNumbers() { for i := 0; i < 5; i++ { fmt.Println(i) } } func main() { go printNumbers() // 为了让 goroutine 有时间执行 fmt.Scanln() } ``` #### 流程控制 - **`if`**、**`else`**、**`else if`**:用于条件判断。 ```go if num > 10 { fmt.Println("Number is greater than 10") } else if num == 10 { fmt.Println("Number is equal to 10") } else { fmt.Println("Number is less than 10") } ``` - **`for`**:Go 语言中唯一的循环结构,可用于实现多种循环方式。 ```go // 基本 for 循环 for i := 0; i < 5; i++ { fmt.Println(i) } // 类似 while 循环 j := 0 for j < 5 { fmt.Println(j) j++ } // 无限循环 for { // 执行某些操作 } ``` - **`switch`**、**`case`**、**`default`**:用于多条件分支判断。 ```go num := 2 switch num { case 1: fmt.Println("Number is 1") case 2: fmt.Println("Number is 2") default: fmt.Println("Number is neither 1 nor 2") } ``` - **`break`**:用于跳出循环或 `switch` 语句。 ```go for i := 0; i < 10; i++ { if i == 5 { break } fmt.Println(i) } ``` - **`continue`**:用于跳过当前循环的剩余部分,直接进入下一次循环。 ```go for i := 0; i < 10; i++ { if i%2 == 0 { continue } fmt.Println(i) } ``` #### 数据类型与声明 - **`var`**:用于声明变量。 ```go var age int var name string = "John" ``` - **`const`**:用于声明常量。 ```go const PI = 3.14 ``` - **`type`**:用于定义新的数据类型。 ```go type Point struct { x, y int } ``` - **`struct`**:用于定义结构体类型。 ```go type Person struct { Name string Age int } ``` - **`interface`**:用于定义接口类型。在 Go 中,只要一个类型实现了接口中的所有方法,就认为该类型实现了这个接口,无需显式声明[^4]。 ```go type Shape interface { Area() float64 } type Circle struct { Radius float64 } func (c Circle) Area() float64 { return 3.14 * c.Radius * c.Radius } ``` - **`map`**:用于声明映射类型。 ```go var scores map[string]int scores = make(map[string]int) scores["Alice"] = 85 ``` - **`chan`**:用于声明通道类型,通道是 Go 语言中用于 goroutine 之间通信的重要工具。 ```go ch := make(chan int) go func() { ch <- 42 }() result := <-ch ``` #### 异常处理 - **`panic`**:用于引发一个运行时错误,程序会停止正常的执行流程。 ```go func main() { panic("Something went wrong!") } ``` - **`recover`**:用于捕获 `panic` 异常,使程序可以从异常中恢复并继续执行。 ```go func main() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered from", r) } }() panic("Something went wrong!") } ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值