type有几种用法:定义结构体, 定义接口, 类型定义, 类型别名, 类型开关
1 定义结构体
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。类似 Java 的类, 我们可以把Go中的struct看作是不支持继承行为的轻量级的“类”。
我们来看看使用type怎么定义结构体:
package main //必须有个main包import ( "fmt")//定义一个 Books结构体type Books struct { title string author string subject string book_id int}type person struct { string int}//结构体内内嵌匿名成员变量定义func main() { b := Books{"雍正王朝", "二月河", "康熙和雍正年间的一系列改革事情", 10} fmt.Println(b.title, b.author, b.subject, b.book_id) //雍正王朝 二月河 康熙和雍正年间的一系列改革事情 10 p := person{"abc", 12} fmt.Println(p.string, p.int)}
2 定义接口
//定义电话接口type Phone interface { call()}
3 类型定义
type name string // 类型定义是完全定义了一种新的类型, name 与 string 是不同的数据类型, 传参和赋值要注意数据类型
在这里要区别 var声明方式
var name string //这里是定义一个string变量
实例: 类型定义使用方法
package main //必须有-个main包import "fmt"func main() { type bigint int64 // 类型定义 var a bigint //等价var a int64 fmt.Printf("a type is %T\n", a) type ( long int64 char byte ) var b long = 11 var ch char = 'b' fmt.Printf("b = %d, ch = %c\n", b, ch)}
实例: 类型定义使用中出现的问题
package main //必须有-个main包import "fmt"func main() { type bigint int64 // 类型定义 var a bigint //等价var a int64 fmt.Printf("a type is %T\n", a) // a type is main.bigint var b int64 = 100 // a = b //Error: cannot use b (type int64) as type bigint in assignment // 解决方法: 使用bigint 转换后 再去赋值 或者 使用类型别名 a = bigint(b) c := int64(a) // 再次转换 fmt.Println(a, b, c)}
注意: int64 和 bigint 是不同类型, 传值和传参要注意数据类型;
除了给已知的类型起别名, 还可以针对新类型(自定义类型)函数进行定义
type handle func(str string) //自定义一个函数func, 类名叫做handle, 传入一个string参数
实例:
package main//必须有个main包import "fmt"type FuncType func(int, int)int //声明一个函数类型, func后面没有函数名//函数中有一个参数类型为函数类型:fFuncTypefunc Calc(a, b int, f FuncType)(result int){ result = f(a, b)//通过调用f()实现任务 return}func Add(a, b int)int{ return a + b}func Minus(a, b int)int{ return a - b}func main(){ //函数调用,第三个参数为图数名字,此函数的委毅,返回值必须和 FuncType 类型一致 result := Calc(1, 1, Add) fmt.Println(result) //2 //第二种使用方法 var f FuncType = Minus fmt.Println("result = ",f(10,2)) //result=8}
4 类型别名
type name = string // name类型与string等价,就是将一个string类型起一个别名叫做name
实例: 使用类型别名
package main //必须有-个main包import "fmt"func main() {//给int64起一个别名叫bigint // 类型别名 type bigint = int64 var a bigint //等价var a int64 fmt.Printf("a type is %T\n", a) // a type is main.bigint var b int64 = 100 a = b // 直接复制, 类型别名 bigint 与 int64 的数据类型是一致的, 可以直接赋值 c := int64(a) // 再次转换 fmt.Println(a, b, c)}
实例: 非本地类型不能定义方法
package mainimport ("time")// 定义time.Duration的别名为MyDurationtype MyDuration = time.Duration// 为MyDuration添加一个函数func (m MyDuration) EasySet(a string) {}func main() {}
代码说明如下:
第 8 行, 为 time.Duration 设定一个类型别名叫 MyDuration。
第 11 行, 为这个别名添加一个方法。
编译上面代码报错,信息如下:
cannot define new methods on non-local type time.Duration
编译器提示:不能在一个非本地的类型 time.Duration 上定义新方法, 非本地类型指的就是 time.Duration 不是在 main 包中定义的, 而是在 time 包中定义的, 与 main 包不在同一个包中, 因此不能为不在一个包中的类型定义方法。
解决这个问题有下面两种方法:
将第 8 行修改为 type MyDuration time.Duration, 也就是将 MyDuration 从别名改为类型;
将 MyDuration 的别名定义放在 time 包中(放置到其他包中)。
6 类型开关
在Go语言中中存在interface{}类型, 可以用来保存任何类型的值, 如果我们需要知道具体保存了哪些类型, 就需要使用类型开关来判断, 具体代码如下:
func classifier(items ...interface{}) { for i,x := range items { switch x.(type) { case bool: fmt.Printf("type #%d is bool",i) case float64: fmt.Printf("type #%d is float64",i) case string: fmt.Printf("type #%d is string",i) case int: fmt.Printf("type #%d is int",i) default: fmt.Printf("type is unknow") } }}