1. 类型比较
类型别名
使用类型别名是一个很不错的习惯,可以让代码看起来更易懂友好。例如在源码 builtin.go
中可以看到别名的使用, type byte = uint8
byte 是 uint8 的别名; type rune = int32
rune 是 int32 的别名
// 注意别名的正确声明
type MyInt1 int
type MyInt2 = int
func main() {
var i int = 0
var i1 MyInt1 = i // #1
var i2 MyInt2 = i // #2
fmt.Println(i1,i2)
}
编译不通过,MyInt1
是一个新类型,MyInt2
是别名,#1
处类型转换将报错。
可修改为类型装换:var i1 MyInt1 = MyInt1(i) // #1
类型比较
go 中不同类型是不能比较的,例如 int 不能和 string 进行比较;false 不能和 0 进行比较。
结构体只能比较是否相等,但是不能比较大小。
type a struct { // 它的变量 可以 == != 比较
name string
age int
}
type b struct { // 它的变量不可以 == != 比较
age int
m map[string]string
}
相同类型的结构体才能够进行比较,结构体是否相同不但与属性类型有关,还与属性顺序相关
如果 struct
的所有成员都可以比较,则该 struct
就可以通过 ==
或 !=
进行比较是否相等,比较时逐个项进行比较,如果每一项都相等,则两个结构体才相等,否则不相等;
注意,数组类型比较,[2]int [3]int
类型不同,不能进行比较。
切片不能进行比较。
2. 常量
常量寻址
常量不同于变量的在运行期分配内存,常量通常会被编译器在预处理阶段直接展开,作为指令数据使用,所以常量无法寻址。
const i = 100
func main() {
fmt.Println(&i, i) // &i compile error
}
iota
iota 通常用来声明常量的整数值累加,请牢记:iota 在 const 关键字出现时将被重置为 0,const 中每新增一行常量声明将使 iota 计数一次。
iota 题一
const (
x = iota
_
y
z = "zz"
k
p = iota
)
const (
name = "name"
c = iota
d = iota
)
func main() {
fmt.Println(x,y,z,k,p)
fmt.Println(c,d)
}
// 0 2 zz zz 5
// 1 2
iota 题二
type Direction int
const (
North Direction = iota
East
South
West
)
func (d Direction) String() string {
return [...]string{"North", "East", "South", "West"}[d]
}
func main() {
fmt.Printf("%d %d /n", North, South)
fmt.Println(South) // Println 会自动使用字符串打印
}
// 0 2
// South
3. 空值与 nil
如果你声明了一个变量但是没有对它进行赋值操作,那么这个变量就会有一个类型的默认零值。
bool -> false
numbers -> 0
string -> ""
pointers -> nil
slices -> nil
maps -> nil
channels -> nil
functions -> nil
interfaces -> nil
可见 nil 只能赋值给 指针、chan、func、interface、map 或 slice 类型的变量
var p *int
p == nil // true
*p // panic: invalid memory address or nil pointer dereference
指针表示指向内存的地址,如果对为nil的指针进行解引用的话就会导致panic。
nil 题一
type People interface {
Show()
}
type Student struct{}
func (stu *Student) Show() {}
func main() {
var s *Student
if s == nil {
fmt.Println("s is nil")
} else {
fmt.Println("s is not nil")
}
var p People = s
if p == nil {
fmt.Println("p is nil")
} else {
fmt.Println("p is not nil")
}
}
// s is nil
// p is not nil
当且仅当动态值和动态类型都为 nil 时,接口类型值才为 nil
nil 题二
func Foo(x interface{}) {
if x == nil {
fmt.Println("empty interface")
return
}
fmt.Println("non-empty interface")
}
func main() {
var x *int = nil
Foo(x)
}
// non-empty interface