Go语言简介
优点如下
- 高性能,高并发
- 语法简单,学习曲线平缓
- 丰富的标准库
- 完善的工具链
- 静态链接
- 快速编译
- 跨平台
- 垃圾回收
基础语法
01-hello
第一行package main
表示这个文件属于main包的一部分
fmt
是标准库的包,主要用来往屏幕上输入、输出文字的
package main
import (
"fmt"
)
func main() {
fmt.Println("hello world")
}
如果想要运行的话,输入go run example/01-hello/main.go
02 var
go
是一门强类型语言,每个变量都有自己的类型,常见的有字符串、整型、浮点型、布尔型等。
字符串:可以通过加号拼接,也可以用等号比较两个字符串。
变量的声明
- var name string = “” ,其中string可以省略,这样代码就会自动推导变量的类型
- 变量:=值 ,比如a:=1,表示定义整型变量a的值为1
常量的声明
- const关键字用来声明常量,常量没有确定的类型,会根据上下文自动确定类型
package main
import (
"fmt"
"math"
)
func main() {
var a = "initial" //第一种声明方法,自动判断类型
var b, c int = 1, 2 //第一种声明方法,主动声明类型
var d = true //第一种声明方法,主动判断类型,布尔型
var e float64
f := float32(e) //第二种声明方法
g := a + "foo" //第二种声明方法
fmt.Println(a, b, c, d, e, f) // initial 1 2 true 0 0
fmt.Println(g) // initialfoo
const s string = "constant" //常量
const h = 500000000
const i = 3e20 / h
fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}
03-for
for
的语法是后面跟初始+条件+后续(可以省略任意一个),里面可以continue/break/return
package main
import "fmt"
func main() {
i := 1 //定义变量 赋值
for {
fmt.Println("loop")
break
}
for j := 7; j < 9; j++ {
fmt.Println(j)
}
for n := 0; n < 5; n++ {
if n%2 == 0 {
continue
}
fmt.Println(n)
}
for i <= 3 {
fmt.Println(i)
i = i + 1
}
}
04-if
if
的语法是后面直接跟判断语句(注意:没有括号),每个if/else
后面都要跟花括号,语句在花括号里
很特殊的一点是,可以在判断语句之前加声明语句,声明的变量只能在这个语句的所有条件分支里使用。
package main
import "fmt"
func main() {
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
if 8%4 == 0 {
fmt.Println("8 is divisible by 4")
}
if num := 9; num < 0 {//相当于声明了变量num,值为9
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit") //结果是这个
} else {
fmt.Println(num, "has multiple digits")
}
}
05-switch
switch
后面的变量名,不要括号,不用加break。
package main
import (
"fmt"
"time"
)
func main() {
a := 2
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
case 4, 5:
fmt.Println("four or five")
default:
fmt.Println("other")
}
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
}
06-arr
数组就是一个具有编号且长度固定的元素序列。比如这里的话是一个可以存放5个int元素的数组A。
对于一个数组,可以很方便地取特定索引的值或者往特定索引取存储值,然后也能够直接去打印一个数组。不过,在真实业务代码里面,我们很少直接使用数组,因为它长度是固定的,我们用的更多的是切片。
package main
import "fmt"
func main() {
var a [5]int
a[4] = 100
fmt.Println("get:", a[2])
fmt.Println("len:", len(a))
b := [5]int{1, 2, 3, 4, 5}
fmt.Println(b)
var twoD [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
twoD[i][j] = i + j
}
}
fmt.Println("2d: ", twoD)
}
07-slice切片
切片跟数组很类似,但是它可以动态增加长度,比较像C++里的vector
声明方式为s := make([]string, 3)
这样表示声明了一个长度为3的string类型的切片,但是切片是可以增加长度的!
append
表示追加内容,比如s = append(s, "d")
表示在切片s后面追加内容"d",这样的话会返回一个新的切片,所以前面必须也是切片类型。
切片还可以进行copy
,比如copy(c, s)
表示切片c复制切片s的内容。
切片还支持[begin,end]
进行切片操作,但是不可以为负数
切片可以变为多维数据结构,内部的slice长度可以不一致
package main
import "fmt"
func main() {
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2]) // c
fmt.Println("len:", len(s)) // 3
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s) // [a b c d e f]
c := make([]string, len(s))
copy(c, s)
fmt.Println(c) // [a b c d e f]
fmt.Println(s[2:5]) // [c d e]
fmt.Println(s[:5]) // [a b c d e]
fmt.Println(s[2:]) // [c d e f]
good := []string{"g", "o", "o", "d"}
fmt.Println(good) // [g o o d]
}
08-map
map可以是哈希或是字典,在Go里也有map
声明的时候要指明<key,value>类型,比如m := make(map[string]int)
,这里表示声明了一个map,其中key为string类型,value为int类型
如果某个key在map里不存在的话,那么他的value值为0
为了辨别value值本身为0和key在map里不存在两种情况,应当应两个值来接收r, ok := m["unknow"]
,这样的话不存在的话ok就是false,表示不存在。
delete可以移除某个key值
在声明的时候赋值也是可以的,如m2,m3
注意:Go里map是完全无序的,遍历的时候会随机顺序
package main
import "fmt"
func main() {
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m) // map[one:1 two:2]
fmt.Println(len(m)) // 2
fmt.Println(m["one"]) // 1
fmt.Println(m["unknow"]) // 0
r, ok := m["unknow"]
fmt.Println(r, ok) // 0 false
delete(m, "one")
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
}
09-range
range用来遍历数据结构
在数组上使用range的时候,返回值为索引和每项的值,如果不需要索引的话可以用_代替,这样就会忽略索引
在map上使用range遍历的时候,返回值为key和value,当然也可以只选择返回key值
package main
import "fmt"
func main() {
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums { //遍历数组,i为索引,num为每项的值
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num) // index: 0 num: 2
}
}
fmt.Println(sum) // 9
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m { //遍历map,k为key,v为value
fmt.Println(k, v) // b 8; a A
}
for k := range m {///遍历map,可以只选择返回值为key
fmt.Println("key", k) // key a; key b
}
}
10-函数func
函数里,变量类型是后置的,可以支持返回多个值,第一个是返回结果,第二个是错误信息。
当多个连续的参数为同样的类型时,可以只声明最后一个参数的类型,忽略之前相同类型参数的类型声明。
package main
import "fmt"
func add(a int, b int) int {//表示返回值为int
return a + b
}
func add2(a, b int) int {///a,b都是int类型
return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {///返回的ok为错误信息
v, ok = m[k]
return v, ok
}
func main() {
res := add(1, 2)
fmt.Println(res) // 3
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok) // A True
}