IT评测·应用市场-qidao123.com
标题:
【Go语言圣经2.5】
[打印本页]
作者:
惊落一身雪
时间:
昨天 23:37
标题:
【Go语言圣经2.5】
目标
了解类型界说不仅告诉编译器怎样在内存中存储和处置惩罚数据,还对步伐计划产生深远影响:
内存结构
:类型决定了变量的底层存储(好比占用多少字节、内存布局等)。
操作符与方法集
:类型决定了哪些内置运算符适用于它,以及可否为该类型界说方法,从而扩展它的行为。
语义区分
:通过界说新类型,纵然它们的底层类型雷同,也能明确区分不同概念,制止混用(例如温度单位、索引、文件描述符等)。
可读性与安全性
:使用定名类型可以让代码语义更明确,从而低落出错的风险。
概念
每个变量或表达式都有一个类型,类型描述了值的属性,如数据占用的内存巨细、内部结构、支持哪些操作以及关联的方法集等。
一个 int 类型的变量可能用于表现索引、时间戳或月份;一个 float64 类型的变量可能表现速率或温度。只管底层都是数字,但语义上却截然不同。
内存与数据表现:每个数据类型在内存中的表现方式(如整数占用 32 位或 64 位)由其底层类型决定。定名类型会沿用雷同的存储方式,但在类型体系中赋予它新的含义。
方法与吸收者
**方法的界说:**在 Go 中,可以为任意定名类型界说方法,使得该类型的值具有特定行为(如格式化输出)。
调用示例:fmt.Printf 等函数会自动调用类型的 String 方法,从而定制输出格式。
静态分派:fmt.Printf 等函数会自动调用类型的 String 方法,从而定制输出格式。
要点
类型声明语句
type 新类型名称 底层类型
复制代码
这条语句创建一个新的类型名称,其底层结构与现有类型雷同,但在类型体系中被以为是不同的。例如:
type Celsius float64 // 摄氏温度类型
type Fahrenheit float64 // 华氏温度类型
复制代码
纵然 Celsius 和 Fahrenheit 都基于 float64,它们是两个不同的类型,防止你无意中混用不同温度单位的数据。
定名规则与导出
假如新类型名称的首字符大写,则表现该类型对包外可见(导出)。
Go 语言中关于 Unicode 字母的规则也使得中文定名默认不能导出(Go 1 的规则),但在将来的 Go 2 中可能会调解。
用途
语义区分
:通过界说不同的定名类型(纵然底层雷同)可以让步伐更安全,不会将代表不同概念的值误用在一起。
简化代码
:对于复杂或冗长的类型,用一个简单的名称可以使代码更清楚易读。
类型转换操作
操作形式
类型转换写作 T(x),它不会改变 x 的实际值,只是将它“贴上”新的类型标签
var f Fahrenheit = CToF(BoilingC)
fmt.Println(Celsius(f)) // 将 f 转换为 Celsius 类型
复制代码
限制
:只有当两个类型的底层类型完全雷同时,大概都是指向雷同底层结构的指针时,才能举行转换。
作用
通过类型转换,可以将同样底层数据但语义不同的值显式转换,使得运算和比较变得类型安全。例如
var c Celsius
var f Fahrenheit
// c == f // 编译错误:类型不匹配
fmt.Println(c == Celsius(f)) // 显式转换后可以比较
复制代码
类型与方法
方法集
定名类型不仅是一个新的数据类型,还可以为该类型界说方法,这使得它拥有特定的行为。
func (c Celsius) String() string {
return fmt.Sprintf("%g°C", c)
}
复制代码
这段代码为 Celsius 类型界说了一个 String 方法,在调用 fmt.Printf 时会自动调用该方法来格式化输出。(由于 fmt 包会自动调用 String 方法)(详细一点说:当一个类型实现了 String() string 方法后,它就满足了 fmt 包界说的 Stringer 接口。fmt 包在格式化输出时,会检查传入的值是否实现了该接口,假如实现了,就自动调用 String() 方法来获取该值的字符串表现。)
c := FToC(212.0)
fmt.Println(c.String()) // 输出 "100°C"
fmt.Printf("%v\n", c) // 也输出 "100°C",因为 fmt 包会自动调用 String 方法
复制代码
为类型界说方法不仅增长了代码的可读性,也让类型更具语义。
怎样界说 Celsius 与 Fahrenheit 两个定名类型及它们之间的转换和方法
// Package tempconv performs Celsius and Fahrenheit temperature computations.
package tempconv
import "fmt"
type Celsius float64 // 定义摄氏温度类型
type Fahrenheit float64 // 定义华氏温度类型
// 常量声明
const (
AbsoluteZeroC Celsius = -273.15 // 绝对零度(摄氏)
FreezingC Celsius = 0 // 冰点(摄氏)
BoilingC Celsius = 100 // 沸点(摄氏)
)
// CToF 将摄氏温度转换为华氏温度
func CToF(c Celsius) Fahrenheit {
return Fahrenheit(c*9/5 + 32)
}
// FToC 将华氏温度转换为摄氏温度
func FToC(f Fahrenheit) Celsius {
return Celsius((f - 32) * 5 / 9)
}
// Celsius 的 String 方法,使其输出更友好
func (c Celsius) String() string {
return fmt.Sprintf("%g°C", c)
}
复制代码
Celsius 类型的 String 方法为其提供了定制格式,当使用 fmt 包打印时,会自动调用此方法。
类型比较与运算
支持内置运算符
由于 Celsius 和 Fahrenheit 的底层类型都是 float64,所以它们可以使用底层类型的算术和比较运算符。例如:
fmt.Printf("%g\n", BoilingC-FreezingC) // 输出 "100"
boilingF := CToF(BoilingC)
fmt.Printf("%g\n", boilingF-CToF(FreezingC)) // 输出 "180"
复制代码
留意,直接将 Fahrenheit 与 Celsius 举行运算会导致编译错误,由于它们是不同的定名类型。
比较运算
只有雷同类型之间才能举行直接比较:
var c Celsius
var f Fahrenheit
fmt.Println(c == 0) // "true",0 会被视为 Celsius 类型的零值
fmt.Println(f >= 0) // "true",同理,0 对于 Fahrenheit 也是零值
// fmt.Println(c == f) // 编译错误:类型不匹配
fmt.Println(c == Celsius(f)) // 正确:通过类型转换后比较
复制代码
总结
类型界说描述了变量的内存表现、支持的运算符和方法集,同时区分不同的语义。
将不同的概念界说为不同的定名类型,纵然它们底层雷同,也能在编译期防止错误的混用。(例如,不警惕将温度与文件描述符混用可能引发错误,通过界说不同类型就可以制止这种情况。)
类型转换 T(x) 只改变 x 的类型标签而不改变底层数据。转换要求两个类型有雷同的底层类型或兼容的结构。
方法与类型行为:为定名类型界说方法(如 String 方法),使得在打印和其它操作时可以自动调用,加强了类型的体现力。
新类型继承了底层类型的算术与比较操作,但必须保证操作数类型一致。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/)
Powered by Discuz! X3.4