类型转换
Go 语言不存在隐式类型转换,因此所有的类型转换都必须显式的声明
type_name(expression)
数值类型转换
类型转换只能在定义正确的情况下转换成功,例如从一个取值范围较小的类型转换到一个取值范围较大的类型(将 int16 转换为 int32)。当从一个取值范围较大的类型转换到取值范围较小的类型时(将 int32 转换为 int16 或将 float32 转换为 int),会发生精度丢失(截断)的情况
只有相同底层类型的变量之间可以进行相互转换(如将 int16 类型转换成 int32 类型),不同底层类型的变量相互转换时会引发编译错误(如将 bool 类型转换为 int 类型)
var a int = 10
var b float64 = float64(a)
字符串类型转换
var str string = "10"
var num int
num, _ = strconv.Atoi(str)
接口类型转换
类型断言
类型断言用于将接口类型转换为指定类型,其语法如下
value.(T)
其中 value 是接口类型的变量,T 是要转换成的类型
package main
import "fmt"
func main() {
var i interface{} = "Hello, World"
str, ok := i.(string)
if ok {
fmt.Printf("'%s' is a string\n", str)
} else {
fmt.Println("conversion failed")
}
}
类型转换
在类型转换中,我们必须保证要转换的值和目标接口类型之间是兼容的,否则编译器会报错
package main
import "fmt"
type Writer interface {
Write([]byte) (int, error)
}
type StringWriter struct {
str string
}
func (sw *StringWriter) Write(data []byte) (int, error) {
sw.str += string(data)
return len(data), nil
}
func main() {
var w Writer = &StringWriter{}
sw := w.(*StringWriter)
sw.str = "Hello, World"
fmt.Println(sw.str)
}
变量
标识符
- 由数字(0~9)和字母(A~Z 和 a~z)、下划线(_)组成,但不能以数字开头
- 不可以是关键字或保留字
- 严格区分大小写
- 不能包含空格
声明
Go 语言主要有四种类型的声明语句:var、const、type 和 func,分别对应变量、常量、类型和函数实体对象的声明
var 声明语句可以创建一个特定类型的变量,然后给变量附加一个名字,并且设置变量的初始值
var a int
短变量声明
在函数内部,有一种称为简短变量声明语句的形式可用于声明和初始化局部变量。它以“名字 := 表达式”形式声明变量,变量的类型根据表达式来自动推导
i := 100 // an int
nil 是 Go 语言中预先声明的标识符(非关键字保留字),其主要用来表示引用类型的零值(指针,接口,函数,映射,切片和通道),表示它们未初始化的值
// [src/builtin/builtin.go](https://golang.org/src/builtin/builtin.go#L98)
//
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
nil 是 Go 语言中唯一没有默认类型的非类型化的值,它不是一个未定义的状态,所以不能用于短变量声明
a := nil // 编译出错
初始化
在声明变量时,自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型的默认值:
- 整型和浮点型变量的默认值为 0 和 0.0
- 字符串变量的默认值为空字符串
- 布尔型变量默认为 bool
- 切片、函数、指针变量的默认为 nil
结构体初始化
stu := &Student{
"张三",
24
}
stu := &Student{
Name: "张三",
Age: 24
}
stu := new(Student)
stu.Name = "张三"
stu.Age = 24
赋值
使用赋值语句可以更新一个变量的值,最简单的赋值语句是将要被赋值的变量放在=的左边,新值的表达式放在=的右边
x = 1 // 命名变量的赋值
*p = true // 通过指针间接赋值
person.name = "bob" // 结构体字段赋值
count[x] = count[x] * scale // 数组、slice或map的元素赋值
数值变量也可以支持 ++ 递增和 -- 递减语句,但不支持赋值
a = 1
a++
元组赋值
i, j, k = 2, 3, 5
作用域
一个声明语句将程序中的实体和一个名字关联,比如一个函数或一个变量。声明语句的作用域是指源代码中可以有效使用这个名字的范围
句法块是由花括弧所包含的一系列语句,就像函数体或循环体花括弧包裹的内容一样。句法块内部声明的名字是无法被外部块访问的。这个块决定了内部声明的名字的作用域范围
逃逸分析
- 在某个函数中 new 或字面量创建出的变量,将其指针作为函数返回值,则该变量一定发生逃逸
- 被已经逃逸的变量引用的指针,一定发生逃逸
- 被指针类型的 slice、map 和 chan 引用的指针,一定发生逃逸