数据类型和控制结构
数据类型 #
常量和变量 #
变量:
var varName dataType [ = value ]
var varName = value
varName := value (只能在函数或方法内使用)
常量: 布尔型、字符串型和数值型。
const name = value
基本数据类型 #
| 类型 | 值 |
|---|---|
| 整型 | byte int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr |
| 浮点型 | float32 float64 |
| 复数型 | complex64 complex128 |
| 字符 | rune |
| 字符串型 | string |
| 布尔型 | bool |
字符串类型 #
1、len() 函数求的是字符串字节的长度;
len("H你") = 4
2、Go内置两种字符类型:一种是byte的字节类类型(uint8的别名),另一种是表示Unicode编码的字符rune。 rune在Go内部是int32类型的别名,占用4个字节。Go语言默认的字符编码就是UTF-8类型的,如果需要特殊的编码转换,则使用Unicode/UTF-8标准包。
复合数据类型 #
指针 #
Go中的指针及与指针对指针的操作主要有以下三种:
一普通的指针类型,例如 var intptr *T,定义一个T类型指针变量
二内置类型uintptr,本质是一个无符号的整型,它的长度是跟平台相关的,是一个能足够容纳指针位数大小的整数类型,可进行指针运算。
三是unsafe包提供的Pointer,表示可以指向任意类型的指针。

声明和初始化
func main() {
a := 10
b := &a
fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
fmt.Println(&b) // 0xc00000e018
}
数组 #
声明和初始化
var arr [2]int
var a = [3]int{1, 2, 3}
a := [...]int{1, 2, 3}
a := [3]int{1:1, 2:3}
a := [...]int{1:1, 2:3}
说明
数组是值类型,赋值和传参会复制整个数组。因此改变副本的值,不会改变本身的值。
切片 #
声明和初始化
1、定义切片类型
var a []int //nil
var b = []int{}
var c = []int{1, 2}
2、由数组创建
a := [5]int{1, 2, 3, 4, 5}
s := a[1:3] // s := a[low:high],左闭右开
3、make创建
var a = make([]int, 2, 10)
说明
切片是一个引用类型,它是基于数组类型做的一层封装,它的内部结构包含地址、长度和容量。
map #
声明和初始化
1、定义map类型
var a map[int]string //nil
var b = map[int]string{1:"1", 2:"2"}
2、make创建
var m = make(map[string]int, 2, 10)
说明
map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。
特别用法
//判断某个键是否存在
value, ok := map[key]
struct #
声明和初始化
1、匿名结构体
struct {
FieldName FieldType
}
//在定义的时候初始化,可以赋值给变量
2、自定义struct类型
type TypeName struct {
FieldName FieldType
}
chan #
声明和初始化
1、定义chan类型
var a chan int
var b chan<- int //单向写通道
var c <-chan int //单向读通道
2、make创建
var c = make(chan int)
var c = make(chan int, 10) //10个缓冲的通道
说明
1、无缓冲的通道既可以用于通信,也可用于两个goroutine的同步;有缓冲的通道主要用于通信;
2、若close(chan)后,则写数据会panic,而读数据会返回通道元素的零值;可通过comma, ok表达式判断chan是否关闭;
3、向缓冲区已满的通道写数据会协程阻塞,读取没数据(未关闭)的通道也会协程阻塞;
4、向未初始化的通道读写数据都会造成协程的永久阻塞;
5、重复关闭通道会导致panic。
make和new的区别:
1、make和new都是用来申请内存的;
2、new很少用,一般用来给基本数据类型申请内存,string、int等返回的是对应类型的指针(*string, *int);
3、make是用来给slice、map、chan申请内存的,name函数返回的是对应这三个类型本身。
控制结构 #
if语句 #
if x:= f(); x < y { //初始化语句中声明变量x
return x
} else if x > z {
return z
} else {
return y
}
switch语句 #
switch i := f(); i {
case a:
fmt.Println("1")
case b:
fmt.Println("2")
fallthrough //强制执行下一个case语句,不再判断下一个case语句是否满足条件
case c:
fmt.Println("3")
default:
fmt.Println("bye")
}
for语句 #
1、类似于C循环中的for语句
for init; condition; post {}
2、类似C的while语句
for condition {}
3、类似于C的while(1)死循环
for {}
4、对数组、切片、字符串、map和通道的访问
for k, v := range Type {}
标签和跳转 #
1、使用标签(Label)来标识一个语句的位置;
Label: Statement
2、goto、break、continue可以单独使用,也可以和标签配合使用跳到指定位置;
3、return用于函数和方法的退出。
例如:
if n%2 == 1 {
goto L1
}
for n > 0 {
f()
n--
L1:
f()
n--
}