本篇文章深入探讨了 Go 语言中类型确定值、类型不确定值以及对应类型转换的知识点,后续充沛解析了常量与变量及其高级用法,并举出丰盛的案例。
关注公众号【TechLeadCloud】,分享互联网架构、云服务技术的全维度常识。作者领有10+年互联网服务架构、AI产品研发教训、团队治理教训,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人。
一、类型确定值
类型确定值是与特定数据类型明确绑定的。类型确定值在 Go 中占有很大一部分畛域,包含但不限于常量、变量、函数返回值、构造体字段等。上面是对类型确定值的的示例:
类型确定值在变量申明中
当你在变量申明中明确指定了类型,那么这个变量就是类型确定值。
var x int = 10 // x 是类型确定值,类型为 int
var y string = "Hello" // y 是类型确定值,类型为 string
类型确定值在函数返回值中
函数也能够返回类型确定值。
func sum(a int, b int) int { // 返回值类型明确为 int
return a + b
}
类型确定值在构造体字段中
构造体字段也是类型确定值。
type Person struct {
Name string // Name 是类型确定值,类型为 string
Age int // Age 是类型确定值,类型为 int
}
类型确定值在数组和切片中
数组和切片的元素也是类型确定值。
var arr [3]int = [3]int{1, 2, 3} // arr 是类型确定值,类型为 [3]int
var s []string = []string{"a", "b", "c"} // s 是类型确定值,类型为 []string
类型确定值在接口和类型断言中
当你通过类型断言将接口值转换为某个具体类型时,后果是类型确定值。
var i interface{} = "this is string"
str, ok := i.(string) // str 是类型确定值,类型为 string
类型确定值在类型别名和自定义类型中
即便你创立了一个类型别名或自定义类型,实际上还是与原始类型绑定的类型确定值。
type Length int
var l Length = 10 // l 是类型确定值,类型为 Length
这些例子展现了类型确定值如何渗透到 Go 语言的各个方面,为开发者提供了严格的类型安全性。在编写代码时,对类型有明确的理解能够帮忙你编写更强壮、更平安的程序。
二、类型不确定值
类型不确定值是没有明确类型的值。这些值不是与任何具体的数据类型绑定的,因而在编译时,Go 编译器会依据上下文来推断其类型。在 Go 中,类型不确定值是一个相当乏味和多面性的概念。这些值存在于常量申明、算术运算、以及一些内建函数中。上面是对类型不确定值的的示例:
在算术运算中的类型不确定值
当你应用类型不确定值进行算术运算时,后果也是类型不确定值,除非运算中有一个类型确定值,这种状况下,后果将是类型确定值。
const c = 3 // 类型不确定值
var d int = 2 // 类型确定值
// e 仍然是类型不确定值,因为参加运算的两个值都是类型不确定值
const e = c * c
// f 是类型确定值,因为参加运算的有一个类型确定值
var f = c * d
在内建函数中的类型不确定值
一些 Go 的内建函数(如 len
)返回类型不确定值。
const s = "hello world"
const l = len(s) // l 是类型不确定值
类型不确定值与默认类型
每个类型不确定值都有一个与之关联的默认类型,通常是基于字面量或者运算表达式。
const g = 42.0 // 默认类型是 float64
const h = 'x' // 默认类型是 rune
类型不确定值在数组长度申明中
在数组长度申明中也可应用类型不确定值。
const size = 4
var arr [size]int // 编译器推断 size 为 int
类型不确定值与 iota
iota
也是类型不确定值,常常用于枚举。
const (
zero = iota // zero 是 0
one // one 是 1
)
三、显式类型转换与类型推断
在 Go 语言中,类型转换和类型推断是两个相当重要的概念。它们独特定义了如何在编译和运行时解决不同类型的值。咱们将具体探讨这两个概念,并通过示例来说明其用法和重要性。
显式类型转换
显式类型转换是通过语法明确地将一个数据类型转换为另一个数据类型的操作。
定义
在 Go 中,显式类型转换的语法是 T(v)
,其中 T
是指标类型,而 v
是要转换的值。
var x float64 = 42.0
var y int = int(x) // 显式地将 float64 转换为 int
限度与束缚
显式类型转换并不总是无效的。转换的合法性取决于源类型和指标类型。例如,不能间接将一个构造体类型转换为整数或者浮点数。
type myStruct struct {
field int
}
var a myStruct
// var b int = int(a) // 这是不非法的
类型推断
类型推断是编译器主动推断变量类型的过程。在 Go 中,这通常产生在应用 :=
进行变量初始化时。
定义
当应用 :=
操作符申明变量但没有明确指定类型时,Go 编译器会依据右侧表达式的类型来推断变量的类型。
z := 42 // 类型被推断为 int
在简单表达式中的类型推断
在波及多种类型的简单表达式中,Go 会尽量进行类型推断以满足表达式的类型须要。
var m float64 = 3.14
n := int(m) + 42 // int(m) 显式转换,后果类型推断为 int
类型推断与类型不确定值
类型推断也实用于类型不确定值。编译器会依据上下文来推断其最合适的类型。
const p = 5 // 类型不确定值
var q = p // 类型推断为 int,因为 p 的默认类型是 int
四、常量
在 Go 语言中,常量(Constant)是不可扭转的值,这一点与变量有显著区别。一旦一个常量被定义,它的值就不能再被扭转。常量能够是类型不确定值或类型确定值。
类型不确定常量
类型不确定常量是没有明确类型的常量。这些常量不是与任何具体的数据类型绑定的,因而在编译时,Go 编译器会依据上下文来推断其类型。
const a = 42 // a 是类型不确定值,因为没有明确指定类型
类型确定常量
类型确定常量是与特定数据类型明确绑定的常量。
const c int = 42 // c 是类型确定值,因为其类型明确为 int
常量申明中的主动补全
在常量申明块中,你能够省略后续常量的类型和值,它们会主动补全。
const (
x int = 10
y // y 也是 int 类型,值为 10
)
应用 iota
在常量申明中
iota
是一个非凡的常量生成器,次要用于创立一组递增的整数常量。
const (
zero = iota // zero 的值为 0
one // one 的值为 1
two // two 的值为 2
)
常量的可见性和可寻址性
常量能够是导出或非导出的,取决于它的名称是否以大写字母结尾。常量不是可寻址的。
const ExportedConst = "I am visible" // 可导出的常量
const unExportedConst = "I am not visible" // 不可导出的常量
常量溢出和默认类型
一个类型不确定常量所示意的值可能会溢出其默认类型。在这种状况下,只有当这个常量被用于一个能够包容该值的上下文时,编译才会胜利。
const big = 1 << 100 // 默认类型为 int,但值会溢出
var bigInt = big >> 99 // big 被用于一个 int64 上下文,没有溢出
字符串常量
字符串常量是蕴含在双引号中的一系列字符。
const hello = "Hello, world!"
布尔常量
布尔常量只有两个可能的值:true
和 false
。
const flagTrue = true
const flagFalse = false
枚举常量
通过应用 iota
,你能够创立一组递增的整数常量,通常用于枚举。
type Weekday int
const (
Sunday Weekday = iota
Monday
Tuesday
// ...
Saturday
)
复数常量
Go 反对复数类型,并且你能够创立复数常量。
const complexConst = 1 + 2i
强制类型转换
你能够通过强制类型转换将一个常量转换为另一种类型。
const integer = 42
const floatType = float32(integer)
计算表达式中的常量
常量也能够是计算表达式的后果,但表达式必须只蕴含常量值。
const calculated = 3 * 2 // 6
常量数组和切片
须要留神的是,在 Go 中,数组大小须要是常量。但切片和映射的大小能够动静扭转,因而它们不能是常量。
const arraySize = 5
var arr [arraySize]int // 非法
五、变量
变量是存储数据值的存储单元,其值能够在运行时扭转。在 Go 语言中,变量的应用非常灵活但又具备严格的类型安全性。
变量申明和赋值
根本申明
应用 var
关键字进行变量申明。
var x int
同时申明和赋值
var y int = 42
或者应用短变量申明模式:
z := 42
多变量申明
var a, b, c int
或者
var (
d int
e float64
)
类型形容
根本类型
包含 int
, float64
, bool
, string
等。
var integerVar int = 10
var floatVar float64 = 10.99
var boolVar bool = true
var stringVar string = "Hello, Go"
数值类型
Go 反对多种数值类型,包含 int8
, int16
, int32
, int64
, uint8
, uint16
, uint32
, uint64
, float32
, float64
等。
var smallInt int8 = 127
var largeInt int64 = 9223372036854775807
var unsignedInt uint16 = 65535
var floatNum float32 = 3.141592
字符和字符串
Go 有 rune
和 byte
类型来示意 Unicode 字符和 ASCII 字符。
var asciiChar byte = 'A'
var unicodeChar rune = '你'
var str string = "Hello, World!"
布尔类型
布尔类型只有两个值:true
和 false
。
var isActive bool = true
var isCompleted bool = false
指针
Go 反对指针类型,但不反对指针运算。
var pointer *int
x := 42
pointer = &x
数组和切片
var arrayExample [5]int = [5]int{1, 2, 3, 4, 5}
var sliceExample []int = arrayExample[1:4]
映射(Maps)
var countryCapitalMap map[string]string
countryCapitalMap = make(map[string]string)
countryCapitalMap["France"] = "Paris"
构造体(Structs)
type Employee struct {
ID int
Name string
Salary float64
}
var emp Employee
接口(Interfaces)
type Shape interface {
Area() float64
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
var s Shape = Circle{5.0}
函数类型
Go 中,函数也是一种类型,能够作为参数传递。
type AddFunc func(a int, b int) int
var add AddFunc = func(a int, b int) int {
return a + b
}
通道(Channels)
var messageChannel chan string = make(chan string)
复合类型
例如数组、切片、映射、通道、构造体和接口。
数组
var arr [5]int
切片
var slice []int
映射
var mapping map[string]int
通道
var ch chan int
构造体
type Person struct {
name string
age int
}
var p Person
接口
type Geometry interface {
Area() float64
}
var g Geometry
值的可寻址性
Go 语言中有些变量是可寻址的,意味着你能够获取这个变量的内存地址。
var myVar int = 42
var p *int = &myVar
变量作用域
在 Go 中,变量能够有不同的作用域:全局作用域、包内作用域、函数作用域、代码块作用域等。
var globalVar int // 全局作用域
func myFunction() {
var functionVar int // 函数作用域
{
var blockVar int // 代码块作用域
}
}
七、常量和变量的高级用法
在 Go 编程中,常量和变量不仅仅是数据存储的简略形式。它们有各种高级用法,能够用来优化代码、提高效率或实现简单的编程模式。
常量的高级用法
枚举和 iota
Go 通过 iota
关键字反对枚举类型的实现。这在一组常量申明中是十分有用的。
const (
Monday = iota + 1 // Monday = 1
Tuesday // Tuesday = 2
Wednesday // Wednesday = 3
)
类型别名
应用类型别名,你能够将常量限度为自定义类型。
type Weekday int
const (
Sunday Weekday = iota
Monday
// ...
)
无类型和有类型常量
无类型的常量能够用在多种场合,它们会依据上下文进行类型推断。
const x = 42 // 无类型常量
var i int = x
var f float64 = x
变量的高级用法
变量的作用域
Go 反对块级作用域。通过 var
关键字在不同级别(全局、包级别、函数级别等)申明变量,你能够控制变量的可见性。
var globalVar = 42 // 全局变量
func main() {
var funcVar = "I'm local" // 函数级别变量
}
提早初始化
应用 init()
函数,你能够在程序开始执行前初始化变量。
var complexVar complex128
func init() {
complexVar = cmplx.Sqrt(-5 + 12i)
}
指针和地址操作符
尽管 Go 语言没有提供指针运算,但它容许你通过地址操作符 &
和解援用操作符 *
来操作指针。
x := 42
p := &x
fmt.Println(*p) // 输入 42
应用标签(Tags)和构造体
在构造体中,你能够应用标签(tags)来附加元数据,这在序列化和反序列化时十分有用。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
关注公众号【TechLeadCloud】,分享互联网架构、云服务技术的全维度常识。作者领有10+年互联网服务架构、AI产品研发教训、团队治理教训,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人。
如有帮忙,请多关注
集体微信公众号:【TechLeadCloud】分享AI与云服务研发的全维度常识,谈谈我作为TechLead对技术的独特洞察。
TeahLead KrisChang,10+年的互联网和人工智能从业教训,10年+技术和业务团队治理教训,同济软件工程本科,复旦工程治理硕士,阿里云认证云服务资深架构师,上亿营收AI产品业务负责人。
发表回复