Go语言入门:基础语法(一)|青训营笔记

231 阅读6分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记

一. Go历史

1.诞生时间

Go 语言起源 2007 年,并于 2009 年正式对外发布。它从 2009 年 9 月 21 日开始作为谷歌公司 20% 兼职项目,即相关员工利用 20% 的空余时间来参与 Go 语言的研发工作。

  • 2007 年 9 月 20 日的下午,在谷歌山景城总部的一间办公室里,谷歌的大佬级程序员 Rob Pike在等待一个 C++ 项目构建的过程中和谷歌的另外两个大佬级程序员 Robert Griesemer和 Ken Thompson进行了一次有关设计一门新编程语言的讨论。

    • 计算机硬件技术更新频繁,性能提高很快。目前主流的编程语言发展明显落后于硬件,不能合理利用多核多CPU的优势提升软件系统性能。
    • 软件系统复杂度越来越高,维护成本越来越高,目前缺乏一个足够简洁高效的编程语言。
    • 企业运行维护很多c/c++的项目,C/C++程序运行速度虽然很快(因为采用静态编译),但是编译速度却很慢,同时还存在内存泄露的一系列困扰需要解决。

2. 为什么使用Go

  1. 简单好记的关键词和语法。轻松上手,简单易学。
  2. 更高的效率。比Java,C++等拥有更高的编译速度,同时运行效率媲美C,同时开发效率非常高。
  3. 生态强大,网络上库很丰富,很多功能使用Go开发非常简单。
  4. 语法检查严格,高安全性。
  5. 严格的依赖管理,go mod命令。
  6. Go拥有强大的编译检查、严格的编码规范和完整的软件生命周期工具,具有很强的稳定性,稳定压倒一切。
  7. 跨平台交叉编译,windows就可以编译出mac,linux上可执行的程序。
  8. 异步编程复杂度低,易维护,GO 语言中 Channel 设计,异步程序写起来非常自然。
  9. 语言层面支持并发,go关键字(协程)使得go的并发效率极高。
  10. 严格的语法规范,所有程序员写出来的代码都是一样的,对大团队来说,非常友好。
  11. Go 的并发、性能、安全性、易于部署等特性,使它很容易成为“云原生语言”。容器和云的使用上非常广

二。GO基础语法

1.Hello world

第一行 package main代表这个文件属于main包的一部分,main包也就是程序的入口包。第三行导入了标准库里的FMT包,这个包主要是用来往屏幕输入和输出字符串、格式化字符串。

package main

import (
	"fmt"
)

func main() {
	fmt.Println("hello world")
}

2.变量

go语言是一门强类型语言,每一个变量都有它自己的变量类型。常见的变量类型包括字符串、整数、浮点型、布尔型等。go语言的字符串是内置类型,可以直接通过加号拼接,也能够直接用等于号去比较两个字符串。在go语言里面,大部分运算符的使用和优先级都和C或者C++类似,这里就不再概述。

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)                // initialapple

	const s string = "constant"
	const h = 500000000
	const i = 3e20 / h
	fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}

3.if else

go语言里的if else写法和C或者C++类似。第一个不同点是if后面没有括号。如果你写了括号的话,那么在保存的时候你的编辑器会自动把你去掉。第二个不同点是Golang里面的if,它后面必须接大括号,不能像C或者C++一样,直接把if里面的语句同一行。

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 {
		fmt.Println(num, "is negative")
	} else if num < 10 {
		fmt.Println(num, "has 1 digit")
	} else {
		fmt.Println(num, "has multiple digits")
	}
}

4.循环

在go里面没有while循环、do while循环,只有唯一的一种for循环。最简单的for循环就是在for后面什么都不写,代表一个死循环。循环途中你可以用break跳出,也可以使用经典的c循环,在循环里面,你可以用break或者continue来跳出或者继续循环。

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
	}
}

5.switch

go语言里的switch分支结构,看起来也和C或者C++比较类似。但有一个很大的不同是,在c++里面,switch case 如果不加break的话会继续往下跑完所有case,而在go语言里是不用加break的。相比C或者C++,go语言里的break更加强大。可以使用任意的变量类型,甚至可以用来取代任意的if else 语句。你可以在switch后面不加任何的变量,然后在case里面写条件分支。这样代码会更加清晰

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")
	}
}

6.数组

数组就是一个具有编号且长度固定的元素序列。对于一个数组,可以很方便地取特定索引的值或者往特定索引存储值。不过,在真实业务代码里面,我们很少直接使用数组,因为他的长度是固定的,我们用的更多的是切片。

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)
}


7.切片

切片不同于数组,它可以任意更改长度,使之有更多丰富的操作。比如我们可以用make来创建一个切片,可以像数组一样去取值,使用append来追加元素。注意append的用法的话,你必须把append的结果赋值为原数组。因为slice的原理实际上是它存储了一个长度和一个容量,加一个指向一个数组的指针,在你执行append操作的时候,如果容量不够的话,会扩容并返回新的slice。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]
}