类型转换,指针,变量的生命周期,常量,模拟枚举,类型别名和类型定义

1、类型转换

在必要以及可行的情况下,一个类型的值可以被转换成另一种类型的值。由于Go语言不存在隐式类型转换,因此所有的类型转换都必须显式的声明:

valueOfTypeB = typeB(valueOfTypeA)

类型转换只能在定义正确的情况下转换成功,例如从一个取值范围较小的类型转换到一个取值范围较大的类型(将 int16 转换为 int32)。当从一个取值范围较大的类型转换到取值范围较小的类型时(将 int32 转换为 int16 或将 float32 转换为 int),会发生精度丢失(截断)的情况。

只有相同底层类型的变量之间可以进行相互转换(如将 int16 类型转换成 int32 类型),不同底层类型的变量相互转换时会引发编译错误(如将 bool 类型转换为 int 类型)。

浮点数在转换为整型时,会将小数部分去掉,只保留整数部分。

2、指针

指针(pointer)在Go语言中可以被拆分为两个核心概念:

  • 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。
  • 切片,由指向起始元素的原始指针、元素数量和容量组成。

1)指针地址和指针类型

一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。当一个指针被定义后没有分配到任何变量时,它的默认值为 nil。

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用在变量名前面添加&操作符来获取变量的内存地址。

2)获取指针指向的地址的值

使用&操作符对普通变量进行取地址操作并得到变量的指针后,可以对指针使用*操作符取值。

3)创建指针的另一种方法——new()函数

Go语言还提供了另外一种方法来创建指针变量,格式如下:

new(类型)

new() 函数可以创建一个对应类型的指针,创建过程会分配内存,被创建的指针指向默认值。

3、变量的生命周期

对于在包级别(函数外部)声明的变量来说,它们的生命周期和整个程序的运行周期是一致的,而相比之下,局部变量的生命周期则是动态的,每次从创建一个新变量的声明语句开始,直到该变量不再被引用为止,然后变量的存储空间可能会被回收。

编译器会自动选择在栈上还是在堆上分配局部变量的内存空间,使用 var 或 new 关键字声明变量并不会影响编译器的选择。

4、常量

1)定义

Go语言中的常量使用关键字 const 定义,用于存储不会改变的数据,常量是在编译时被创建的,即使定义在函数内部也是如此,并且只能是布尔型、数字型(整数型、浮点型和复数)和字符串型。由于编译时的限制,定义常量的表达式必须为能被编译器求值的常量表达式。

常量的定义和变量的定义很相似:

const name [type] = value

也可以批量声明多个常量。如果是批量声明的常量,除了第一个外其它的常量右边的初始化表达式都可以省略,如果省略初始化表达式则表示使用前面常量的初始化表达式,对应的常量类型也是一样的。

2)iota常量生成器

常量声明可以使用 iota 常量生成器初始化,它用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个 const 声明语句中,在第一个声明的常量所在的行,iota 将会被置为 0,然后在每一个有常量声明的行加一。

3)无类型常量

Go语言的常量有个不同寻常之处。虽然一个常量可以有任意一个确定的基础类型,例如 int 或 float64,但是许多常量并没有一个明确的基础类型。

编译器为这些没有明确的基础类型的数字常量提供比基础类型更高精度的算术运算,可以认为至少有 256bit 的运算精度。这里有六种未明确类型的常量类型,分别是无类型的布尔型、无类型的整数、无类型的字符、无类型的浮点数、无类型的复数、无类型的字符串。

对于常量面值,不同的写法可能会对应不同的类型。例如 0、0.0、0i 和 \u0000 虽然有着相同的常量值,但是它们分别对应无类型的整数、无类型的浮点数、无类型的复数和无类型的字符等不同的常量类型。同样,true 和 false 也是无类型的布尔类型,字符串面值常量是无类型的字符串类型。

示例:

package main

import "fmt"

func main() {
	const pi = 3.1415926
	fmt.Println("pi=", pi)
	const (
		x = 1
		y = 2
	)
	fmt.Printf("x = %v, y = %v\n", x, y)
	const (
		a = 998
		b
		c
	)
	fmt.Printf("a = %v, b = %v, c = %v\n", a, b, c) // a = 998, b = 998, c = 998
	const (
		red = iota
		white
		black
	)
	fmt.Printf("red = %v, white = %v, black = %v\n", red, white, black) // red = 0, white = 1, black = 2
	
}

  

5、模拟枚举

Go语言现阶段没有枚举类型,但是可以使用 const 常量来模拟枚举类型。

示例:

package main

import "fmt"

func main() {
	const (
		x = 1 << iota
		y
		z
	)
	fmt.Printf("x = %v, y = %v, z = %v\n", x, y, z) // x = 1, y = 2, z = 4
}

  

 6、类型别名和类型定义

类型别名的写法为:type TypeAlias = Type

类型别名规定:TypeAlias 只是 Type 的别名,本质上 TypeAlias 与 Type 是同一个类型。

类型定义的写法为:type NewType Type

示例:

package main

import "fmt"

type NewInt int32
type IntAlias = int32
func main() {
	var x NewInt = 1
	var y IntAlias = 1
	fmt.Printf("%T\n", x) // main.NewInt
	fmt.Printf("%T\n", y) // int32
}

  

猜你喜欢

转载自www.cnblogs.com/ACGame/p/11872366.html