Go 语言优势
- 高性能和高并发:内部支持很便利,可以不用像Java、C++等编程语言需要第三方
库,只需要自身标准库或者基于标准库的第三方库。
- 语法简单、学习曲线平缓:上手容易,语法简洁易懂易学,学起来难度跨度不大,无论是初学者还是已经学过其他编程语言的同学来说都比较容易学。
- 丰富的标准库:标准库就可以大大满足平时需求,这会大大降低我们学习新的第三方库的时间成本,而且节省精力。
- 完善的工具链:内置完整的单元测试框架、代码格式化、格式检查等等非常多的工具。
- 静态链接:只需要拷贝编译后的唯一 一个可执行文件,不加任何东西就能部署运行;在线上的容器环境下运行,部署非常方便快捷。相比之下,像C++ ,则需要附加一堆文件才行,而且文本不正确的话还会崩溃;Java是需要附加一个庞大的 JRE 才能运行。
- 快速编译:Go 语言拥有静态语言里几乎最快的编译速度。
- 跨平台:能在VSCode、IDEA、Goland等各大平台运行,也能开发Android、iOS软件;甚至还能在路由器和树莓派里运行。
- 垃圾回收:自带垃圾回收,和Java类似,写代码的时候不用考虑内存的分配释放。
Go 语言基础语法-上
变量的声明
常见的变量包括字符串、整型、浮点型,在 Go 语言里,字符串是内置类型,所以可以直接通过 +号去拼接,那么,直接用 = 比较两个字符串也是可以的。
至于运算符的优先级,和C/C++的很类似,不是很需要特殊记。
func main() {
var a = "inital" //第一种声明方式
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)
fmt.Println(g)
const s string = "constant"
const h = 500000000
const i = 3e20 / h
fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}
-
第一种声明方式是直接赋值,
var万能类型头,自动识别。 -
第二种声明方式是 --- 前面写变量名, 后面写变量类型。
-
第三种声明方式:
f := float32(e)--- 变量名 + 冒号等于 + 值 -
常量:就是把
var换成const就行了,同样的,golang 里的常量也是没有确定类型,会根据上下文自动确定类型。
if-else
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 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
}
- if 后的判断条件是不需要写括号括起来的,就算括起来,保存编译的时候编译器也会自动去掉。
- if 后**必须跟大括号**,不能和 C/C++ 一样不带大括号写在同一行或者下一行
小tips: fmt.Println(),如果里边是多个参数,逗号隔开之后,打印输出的结果每两个参数之间会自动加一个空格,这一点和Java是不一样的。我觉得相同点相同记,不同点区分记,这样其实也挺快的记的。
for 循环
在 golang 里边,没有 while 和 do-while 循环,只有 for 一种循环。
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++
}
}
- 单独一个 for 跟着大括号代表一个死循环。
- 比较熟悉的就是第二个循环体了,比较像 C/C++ 和 Java,但是和py 一样,golang 里的for 循环的条件是不需要加括号括起来的。需要注意的一点是 --- for 循环条件里的三部分,缺任何一个部分都可以
switch
func main() {
a := 2
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("2")
case 3:
fmt.Println("3")
case 4, 5:
fmt.Println("4 or 5")
default:
fmt.Println("other")
}
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("before noon")
default:
fmt.Println("after noon")
}
}
这里golang 和其他几个语言最大的区别就是,每个 case 都不用自己写 break 关键字,golang 会自动帮我们加上。
相比其他语言,golang 里的 switch 更强大,可以使用任意的变量类型,比如字符串、结构体,甚至可以用来取代任意的 if-else 语句--- 在 switch 后不加变量,直接跟大括号,然后 case 后跟 if 原本的判断语句即可 。相比多个 if-else 更加通俗易懂。
数组
实际应用过程中很少直接使用数组,因为它的长度是固定的。大多会使用**切片。**
func main() {
var a [5]int
a[4] = 100 //golang 里数组下标同样也是从0开始
fmt.Println(a[4], 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)
}
切片 slice
func main() {
s := make([]string, 3)
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2])
fmt.Println("len:", len(s))
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s)
c := make([]string, len(s))
copy(c, s)
fmt.Println(c)
fmt.Println(s[2:5]) //[c d e] 下标 [2, 5)左闭右开区间
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)
}
-
相当于可变长度的数组,可以任意时刻去更改长度,内置操作也更丰富。
-
用
make来创建一个切片,可以像给数组赋值一样挨个给切片元素赋值。 -
用
append方法来增加元素,如果 append 的时候容量不够了会发生扩容,返回一个新的切片,所以必须要赋值回去。 -
在用 make 创建一个 slice (切片)时,可以直接用
len()获取已有切片或数组的长度当作第二个参数。 -
copy方法,两个参数,作用是把后一个slice 的值挨个复制对应到前一个。 -
和 py 不同的是不支持负数索引。
map
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"] //作用是来接收map里的该key是否存在
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)
}
- 格式里边的
map[string]int,中括号里边的是 key 的类型,后边的是 value 的类型。创建完之后可以通过方括号加key 对value赋值。 - golang 的map 完全无序
range
func main() {
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num)
//index: 0 num: 2
}
}
fmt.Println(sum) //9 --- 2+3+4
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v) // b B; a A
}
for k := range m {
fmt.Println("key", k) //key a; key b
}
}
- 其实就是类似于增强for ,只不过稍有区别 :golang 的对于数组会返回两个值 --- 一个下标索引,一个对应的值;我们如果不想要索引,可以用下划线替代第一个 for 循环里的 i ;;;然后如果是 map 的话就好理解了,k-v键值对。