数组
同一种数据类型元素的集合。数组的长度是数组类型的一部分
var a [3]int
数组的初始化(如果不初始化,默认元素都是零值)
// 1a1 = [3]bool{true, true, true}// 2 根据初始值自动推断a2 = [...]int{1,2,3,4,5,6,7,8,9}// 3 根据索引初始化a3 := [5]int{0:1, 4:2}
数组的遍历
citys := [...]string{"上海""深圳""广州"}// 索引编译for i:=0;i<len(citys);i++{fmt.Println(citys[i])}// for rangefor i, v := range citys {}
多维数组
// [[1 2] [3 4] [5 6]]var a11 [3][2]inta11 = [3][2]int {[2]int {1,2},[2]int {3,4},[2]int {5,6},}
多维数组的遍历
for _, v1 := range a11 {for _, v2 := range v1 {}}
数组是值类型,赋值时总是创建了新的地址
b1 := [3]int {1,2,3}b2 := b1 // 赋值时创建是创建了新的地址,并放入,修改b2不影响b1b2[0] = 100
数组支持
==!=, 因为内存总是被初始化过的[n]T表示指针数组, [n]T 表示数组指针
切片
Go 语言中的切片有三种初始化的方式:
- 通过下标的方式获得数组或者切片的一部分;
- 使用字面量初始化新的切片;
- 使用关键字
make创建切片:arr[0:3] or slice[0:3]slice := []int{1, 2, 3}slice := make([]int, 10)
切片是引用类型,不支持直接比较,只能和nil比较。切片的本质就是一个框,框住了一块连续的内存,属于引用类型,真正的数据都是来自于底层数组。
// 与nil 比较t == nil
切片拥有自己的长度和容量,可以通过len()求长度,使用内置的cap()求切片的容量
可以使用append方法来为切片添加元素,索引不能超过容量,否则会产生越界错误.使用append相当于创建了一块新的内存给切片。(底层数组变了,即地址变了)
a3 = append(a3, 111)
使用**copy**来复制切片,会划分一块新的地址。简单的赋值只是做了地址引用,而使用copy则是划分了新的地址给它
a1 := []int{1,3,5}a2 := a1var 3 make([]int, 0, 3)copy(a3, a1)
切片没有删除的专用方法,需要使用切片的本身特性来删除。 …运算符表示将一个切片的所有元素追加到另一个切片里
a := []int{1,2,3,4}// 删除索引为2的元素a = append(a[:2], a[3:]...)
字典(哈希表)
go语言中提供映射关系,无序的,是引用类型(需要初始化)
var a map[string]inta = make(map[string]int, 0) // 自动扩容a["1"] = 1value, ok := a["1"] // 约定俗称使用ok接收返回的布尔值// 使用key value来表示键值对hash := map[string]int{"1": 2,"3": 4,"5": 6,}
遍历
for k,v := range a {}// 只遍历keyfor k := range a {}// 只遍历valuefor _,v := range a {}
删除
delete(a,"1")
map和slice的组合: 要初始化
- 元素为map类型的切片
var s1 = make([]map[int]string, 0, 10) //初始化slice,访问第一个元素报越界错误var s2 = make([]map[int]string, 1, 10) //初始化slice,访问第一个元素报未初始化map错误s1[0] = make(map[int]string, 1)s1[0][100] = "abc"
- 值为切片类型的map
var m1 = make(map[string][]int, 10)m1['北京'] = []int{10, 20, 30}
字符串
utf-8。
go语言中的双引号只能用双引号。go语言中的单引号包裹的是字符。
字符:’h’ ‘你’ ,单独的字母,汉字,符号表示一个字符。
一个AscII等于一个字节(8位)
一个utf8编码的汉字等于3个字节
多行字符串
s2=`123456789`
字符串常用操作
- len(str)
+或fmt.Sprintf- strings.Split 分割
- strings.contains 包含
- strings.HasPrefix, strings.HasSuffix 前缀/后缀判断
- strings.Index(), strings.LastIndex() 子串出现的位置
- strings.Join(a[]string, sep string) join操作
流程控制
if
if age > 18 {} else if {} else {}
作用域
if age := 19; age >18 { //age只在if条件判断中生效} else {}
不支持三元操作符(三目运算符) > a > b ? a : b。
switch
switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上直下逐一测试,直到匹配为止。 Golang switch 分支表达式可以是任意类型,不限于常量。可省略 break,默认自动终止。
switch var1 {case val1:...case val2:...default:...}
switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。
switch x.(type){case type:statement(s)case type:statement(s)/* 你可以定义任意个数的case */default: /* 可选 */statement(s)}
select
select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。
select 是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收。 select 随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该总是可运行的。
select {case communication clause :statement(s);case communication clause :statement(s);/* 你可以定义任意数量的 case */default : /* 可选 */statement(s);}
使用场景:
- 超时判断
```go
var resChan = make(chan int)
// do request
func test() {
select {
case data := <-resChan:
case <-time.After(time.Second * 3):doData(data)
} }fmt.Println("request time out")
func doData(data int) { //… }
2. 退出```go//主线程(协程)中如下:var shouldQuit=make(chan struct{})fun main(){{//loop}//...out of the loopselect {case <-c.shouldQuit:cleanUp()returndefault:}//...}//再另外一个协程中,如果运行遇到非法操作或不可处理的错误,就向shouldQuit发送数据通知程序停止运行close(shouldQuit)
- 判断是否阻塞 ```go //在某些情况下是存在不希望channel缓存满了的需求的,可以用如下方法判断 ch := make (chan int, 5) //… data:=0 select { case ch <- data: default: //做相应操作,比如丢弃data。视需求而定 }
<a name="kAeeG"></a>## for```gofor i :=0;i<10;i++{}
可以省略初始语句
for ;i<10:i++{}
可以省略执行语句
for i < 10{i++}
无限循环
for {}
for range:遍历数组,切片,字符串,map及通道
s := "hello"for i, v := range s {fmt.Printf("%d %c\n", i, v)}
跳出循环break
跳出指定循环
package mainimport ("fmt")func main() {J:for j := 0; j < 5; j++ {for i := 0; i < 10; i++ {if i > 6 {break J //现在终止的是j 循环,而不是i的那个}fmt.Println(i)}}}
跳过continue
