概要
本篇文章主要介绍Go基础语法, 包括变量、常量、方法、数据类型、指针、运算符、控制流等
变量
var a int //定义变量a为int
var a int = 10 //定义变量a为int,并初始化为10
var a = 10 //定义变量并初始化a为10,编译器根据10是int推断出变量a为int
a := 10 //更简练的写法,定义变量并初始化a为10,编译器根据10是int推断出变量a为int
//定义多个变量
var (
a int
b string
c float
)
常量
//定义单个常量
const ErrCodeNotFound = "Not Found"
//定义同类常量
const (
ErrCodeUndefined = itoa
ErrCodeInternal
)
方法
定义方法的关键字是func
//两数相加
//参数 a和b都是int,返回值是int
func add(a, b int) int {
return a + b
}
数据类型
基本数据
- 整型
- 有符合整型: int8、int16、int32、int64
- 无符号整型:uint8(byte)、int16、uint32、uint64
- 浮点型
- float32
- float64
- 布尔型
- bool 只有true(真)和false(假)两个值
其他数据类型
-
数组array
Go中的数组,申请的是一块连续的内存空间,大小不能改变。 一般情况Go中直接使用array的场景并不多。
var a [2]int = {1, 2} //定义包含2个元素int数组 -
字符串string
Go中的string是只读的,可以通过len方法获取字符串的长度,底层实际上是struct
var s1 string = "nihao" s2 := "hello" var s2_len = len(s2) //得到s2的字符串长度 -
切片slice
slice可以简单理解为能动态修改大小的array。slice有两个属性:容量和长度,分别可以使用cap和len方法获取,slice在Go中使用非常频繁
var names []string //定义空slice,cap=0,len=0 names = append(names, "zhangsan") //追加单个元素 names = append(names, []string{"lisi", "wanger"}...) //追加slice capacity := cap(names) //容量,即分配的内存空间大小 length := len(names) // 长度, 即当前有多少个元素 newNames1 := names[0:2] //切片操作,获取从位置0到2的元素(左闭右开)即 [zhangsan lisi] nameNames2 := names[:2] //可以省略开始位置,默认从0开始 nameNames3 := names[1:] //可以省略结束位置,默认到slice结束 preAllocNames := make([]string, 0, 4) //定义容量为4的slice -
map
Go的map是个hashmap,内部是基于数组+链表的实现方案,在Go中使用非常频繁
var m map[int]string //定义一个空map m = make(map[int]string) //使用之前必须make申请内存 m[1] = "zhangsan" //key=1 value=zhangsan name := m[1] //获取key=1的value name, ok := m[1] //第二个返回值ok标识key是否存在 //遍历map for k, v := range m { fmt.Println(k, v) } -
channel
channel是Go中非常重要的一个数据类型,顾名思义作为通道,一般用于goroutine之间的通信。
- 同步channel
- 异步channel
var syncChannel = make(chan int) //申请同步channel var buffer1Channel = make(chan int, 1) //申请缓冲空间为1的channel,和同步channel有很大区别 var bufferChannel = make(chan int, 10) //申请缓冲空间为10的channel //同步channel常用场景 go func() { //异步do something //结束之后通知主线程 syncChannel <- 1 }() //等待任务完成 finished := <-syncChannel if finished == 1 { //do nothing fmt.Println("sync task finished") } //异步channel常用于生产者/消费者模式 go func() { //生产者 for i := 0; i < 10; i++ { bufferChannel <- i } //关闭buffer close(bufferChannel) }() //消费数据 for consumedRes := range bufferChannel { fmt.Println(consumedRes) } -
结构体struct
Go中的结构体作用等同于其他语言的类,用来抽象复杂的数据类型
//Person,有Name和Age两个属性,并且拥有GetAge()方法 type Person struct { Name string Age int } func(p Person) GetAge() int{ return p.Age } //使用方法 var p = Person{ Name: "zhangsan", Age: 28, } fmt.Println(p.GetAge()) -
函数func
func其实也是一种特殊的数据类型,Go中闭包非常常见
var add func(x, y int) int add = func(x, y int) int { return x + y } fmt.Println(add(10, 20))
指针
Go中的指针:变量的地址,不能对指针做运算,所以比较安全 由于Go方法传参都是值传递的方式(闭包是个例外)即形参是实参的一份copy, 如果想达到类似其他语言的引用传递的效果,需要使用到指针。
var a = 1
var p = &a
fmt.Printf("p: %p\n", a, p)
func Change(a *int) {
*a = 10
}
Change(&a)
fmt.Printf("a: %d\n",a) //打印a: 10
运算符
- 算数运算符
- 加法+ 、减法-、乘法*、除法/、取模%
- 逻辑运算符
- 逻辑与&&、逻辑或||、逻辑非!
- 位运算符
- 左移<<、右移>>、异或^、与&、或|
- 关系运算符
- 相等==、不相等!=、大于>、小于<、大于等于>=、小于等于<=
流程控制语句
分支语句
flag := true
if flag {
//do something
} else {
//do something
}
//多分支
a := 10
if a < 0 {
//do something
} else if a > 0{
//do something
} else {
//do something
}
//switch分支
switch a {
case a<0: //无需break,会自动跳出分支,这个和其他语言不一样,切记
case a>0:
default:
}
循环语句
//for第一种形式
for i := 0; i<10; i++ {
}
i := 0
//第二种形式,类似其他语言的while
for i<10 {
i++
}
//第三种形式,迭代,slice、map、channel都支持这种形式
for range c {
}