类型简介
Go语言数据类型简单分简单类型和复合类型

命名类型和未命名类型
-
命名类型:可以通过标识符表示的类型.
例如:Go语言基本类型中预声明的简单类型以及**自定义类型(type)**都是命名类型
-
未命名类型:由预声明类型,关键字和操作符组成(也称为类型字面量)
所以
[]int//这个是未命名类型 type mySlice []int//mySlice就是命名类型 -
注意:未命名类型 == 类型字面量 == 复合类型
底层类型
所有类型都有一个底层类型
-
预声明类型和类型字面量的底层类型是自身
-
自定义类型
type newtype oldtype中newtype的底层类型是oldtype的底层类型(逐层向下查找)

底层类型在类型赋值和强制类型转换时会用到
类型相同和类型赋值
类型相同:
-
两个命名类型相同的条件: 两个类型声明语句相同
var a int var b int //a 和 b类型相同 var c A var d A //c 和 d类型相同 -
命名类型和未命名类型永远不同
-
两个未命名类型相同的条件:类型声明字面量相同且内部元素类型相同
-
别名类型相同
type myInt1 = int //起别名--myInt1和int完全相同 type myInt2 int//自定义类型--myInt2和int是两个类型但底层类型相同
类型赋值:
var a T1//a的类型是T1
var b T2//b的类型是T2
b = a//如果成功说明a可以直接赋值b
-
T1和T2类型相同
-
T1和T2具有相同的底层类型,且T1和T2至少有一个是未命名类型
type mySlice []int var list1 mySlice //mySlice 命名类型 var list2 []int //[]int 未命名类型 list1 = list2 //可以直接赋值 -
T2是接口类型,T1是具体实例对象,且T1可以实现T2(T1的方法集大于等于T2的方法)
// Student 结构体 type Student struct { name string } //方法实现 func (s Student) eat() {} func (s Student) drink() {} //接口 type inter interface { eat() } var stu Student //Student的方法集大于inter接口类型的方法集 var i inter //i是接口类型 i = stu //可以赋值(赋值之后i的静态类型仍是接口,但动态类型是Student,接口) -
T1和T2都是通道类型,具有相同的元素类型,且T1和T2至少有一个是未命名类型(没学到…)
-
nil可以赋值给指针,函数,切片,字典,通道,接口类型
var n *Student = nil -
a是一个可以表示类型T1的字面常量值
类型强制转换
Go是强类型语言,如果不满足自动类型转换的条件,则必须强制类型转换.
格式:var a T = (T)(x)
非常量类型的变量x可以强制转化并传递给类型T,需要满足如下任一条件:
(1)x可以直接赋值给T类型变量.
(2)x的类型和T具有相同的底层类型.
(3)x的类型和T都是未命名的指针类型,并且指针指向的类型具有相同的底层类型。
(4)x的类型和T都是整型,或者都是浮点型。
(5)x的类型和T都是复数类型。
(6)x是整数值或[]byte类型的值,T是string类型。
(7)x是一个字符串,T是[]byte或[]rune。
(8)浮点型,整型之间可以强制类型转换(可能会损失数据精度)
类型方法
类型方法:Go语言面向对象编程的基础…只有命名类型才有方法
自定义类型
自定义类型的关键字type,格式: type newType oldType
newType 和 oldType 具有相同的底层类型,而且都继承了底层类型的操作集(例如底层类型是slice,map,则newType可以进行range访问),但是newType终归是一个新的命名类型.
-
自定义struct类型
struct {//这是一个未命名结构体类型 name string age int } type Student struct{//Student是一个命名结构体类型 name string age int } -
interface{//未命名接口类型 eat() } type name interface {//name是一个命名接口类型 eat() }
方法
Go语言类型方法是对类型行为的封装,GO语言的方法其实是特殊的函数,其将方法接收者作为函数第一个参数
//类型接收者是值类型
func (t typeName)methodName(paramList)(ReturnList){
//method body
}
//类型接收者是指针类型
func (t *typeName)methodName(paramList)(ReturnList){
//method body
}
t :接收者名称可变
typeName:命名类型的类型名
methodName:方法名
paramList:形参列表
ReturnList:返回值列表
例子:
//Student类型
type Student struct {
name string
age int
}
//Student类型的方法
func (s Student) eat() {
fmt.Println(s.name, "正在吃饭")
}
方法调用
-
一般调用:
typeInstanceName.methodName(paramList)typeInstanceName:类型实例名 methodName:类型方法名 paramList:方法实参//方法的调用 s := Student{name: "张三", age: 19}//Student类型对象的创建和初始化 s.eat()//调用方法 -
方法值调用
x的静态类型是T,T存在一个方法M,则x.T就是方法值,将其赋值给一个变量,则可像一个函数名一样使用
f := s.eat f()//方法值调用 -
方法表达式调用
Student.eat(s)//因为方法其实就是特殊的函数 //eat()方法转为函数 func eat(s Student){ fmt.Println(s.name, "正在吃饭") }
方法调用的类型转换
/*
具体类型实例变量直接调用其方法时,编译器会所调用方法进行自动转换,
即使接收者是指针的方法,仍然可以使用值类型变量进行调用。
(1)通过 类型字面量 显式地进行值调用和表达式调用,不会自动转换.
(2)通过 类型变量 进行值调用和表达式调用,在这种情况下,使用值调用方式调用时会进行自动转换,使用表达式调用方式调用时不会进行自动转换.
*/
func main() {
//普通变量调用--自动类型转换
var a = Data{name: "李四"}
a.testValue(1)
a.testPointer(1)
(&a).testValue(2)
(&a).testValue(2)
/*
Data 的方法集是testValue
*Data 的方法集是testValue和testPointer
注释了的都是失败的
*/
//1.通过类型字面量进行的两种调用--不进行自动转换
(*Data)(&struct{ name string }{"张三"}).testPointer(3)//类型字面量 显式调用
(*Data)(&struct{ name string }{"张三"}).testValue(3)
(Data)(struct{ name string }{"张三"}).testValue(3) //
Data.testValue(Data{name: "张三"}, 3) //方法表达式
//失败案例
//Data.testPointer(Data{name: "张三"}, 3)//invalid method expression Data.testPointer
//(Data)(struct{ name string }{"张三"}).testPointer(3)//cannot call pointer method on Data
//2.通过类型变量进行值调用和表达式调用--值调用会自动转换,表达式调用不会自动转换
Data.testValue(a, 4)
//Data.testValue(&a, 4) //invalid method expression Data.testPointer
//Data.testPointer(&a, 4)
//Data.testPointer(a, 4)
(*Data).testPointer(&a, 4)
(*Data).testValue(&a, 4)
//值调用会自动转换--下面这些本身就会自动转换所以赋值也一样
(&a).testValue(4)
a.testPointer(4)
(&a).testPointer(4)
(&a).testValue(4)
//fmt.Println(unsafe.Sizeof(S{}))
}
type Data struct {
name string
}
type S struct{
n1 int
c1 byte
n2 int
}
func (d Data) testValue(n int) {
fmt.Println(d.name, n)
}
func (d *Data) testPointer(n int) {
fmt.Println(d.name, n)
}
本文深入探讨Go语言的类型系统,包括命名类型与未命名类型的区别,底层类型的定义,类型赋值的条件,以及类型转换的规则。详细阐述了类型相同的概念,介绍了自定义类型、接口、方法及其调用,以及方法值和方法表达式的使用。此外,还讨论了类型在方法调用时的自动转换情况。
2547

被折叠的 条评论
为什么被折叠?



