我们一般在定义结构体和接口时会经常使用type关键字,本文会总结golang中type关键字的五种用法。
1、定义结构体
2、定义接口
3、定义函数类型
4、定义类型别名
5、i.(type)类型查询
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
结构体表示一项记录,比如保存图书馆的书籍记录,每本书有以下属性:
type Books struct {
title string
author string
subject string
book_id int
}
可以将结构体理解为面向对象编程中类的属性部分,用了定义类的属性,并保存数据
Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
接口可以让我们将不同的类型绑定到一组公共的方法上,从而实现多态和灵活的设计。
Go 语言中的接口是隐式实现的,也就是说,如果一个类型实现了一个接口定义的所有方法,那么它就自动地实现了该接口。因此,我们可以通过将接口作为参数来实现对不同类型的调用,从而实现多态。
/* 定义接口 */
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
...
method_namen [return_type]
}
/* 定义结构体 */
type struct_name struct {
/* variables */
}
/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
/* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
/* 方法实现*/
}
更多有关接口的知识请见Go中的接口的定义与实现;接口类型
再开始学习之前我们首先复习下函数的定义
func function_name( [parameter list] ) [return_types] {
函数体
}
两个函数类型相同的条件是:拥有相同的形参列表和返回值列表(列表元素的次序、个数和类型都相同),形参名可以不同 。 以下 3 个函数的函数类型完全一样。
func add (a , b int) int { return a + b }
func sub (c int, d int) int { return c - d }
func mul (e int, f int) int { return e * f }
package main
import "fmt"
func add(a, b int) int { return a + b }
func sub(c int, d int) int { return c - d }
func mul(e int, f int) int { return e * f }
func main() {
fmt.Printf("%T\n", add)
fmt.Printf("%T\n", sub)
fmt.Printf("%T\n", mul)
}
执行go run test.go输出结果如下:
func(int, int) int
func(int, int) int
func(int, int) int
通过 type 可以定义函数类型,格式如下
type typeName func(arguments) retType
函数类型也是一种类型,故可以将其定义为函数入参,在 go 语言中函数名可以看做是函数类型的常量,所以我们可以直接将函数名作为参数传入的函数中。
package main
import "fmt"
func add(a, b int) int {
return a + b
}
//sub作为函数名可以看成是 op 类型的常量
func sub(a, b int) int {
return a - b
}
//定义函数类型 op
type op func(a, b int) int
//形参指定传入参数为函数类型op
func Oper(fu op, a, b int) int {
return fu(a, b)
}
func main() {
//在go语言中函数名可以看做是函数类型的常量,所以我们可以直接将函数名作为参数传入的函数中。
aa := Oper(add, 1, 2)
fmt.Println(aa)
bb := Oper(sub, 1, 2)
fmt.Println(bb)
}
实际上byte类型是int8类型的别名,rune类型是int32类型的别名,需要注意的是类型别名与原类型是两种类型,不能直接操作,需要进行类型转换。
package main
import "fmt"
// 定义类型别名
type 字符串 = string
func main() {
// 声明类型别名变量
var str 字符串
// 变量赋值
str = "这是中文"
// 打印数据类型和值
fmt.Printf("type is %T, value is %v\n", str, str)
}
数据类型的判断,有一个方式通过i.(type)结合空接口实现,注意的是该写法必须与switch case联合使用,case中列出实现该接口的类型。示例代码如下
// 实现数据类型的判断
func checkType(i interface{}) string {
switch i.(type) {
case string:
return "string"
case int:
return "int"
case float64:
return "float64"
default:
return "unknown"
}
}
func main() {
// 验证
v1 := "hello world"
v2 := 33
v3 := 45.2
fmt.Printf("the type of v1 is %s\n", checkType(v1))
fmt.Printf("the type of v2 is %s\n", checkType(v2))
fmt.Printf("the type of v3 is %s\n", checkType(v3))
}