Go 语言基础 | 青训营笔记

73 阅读5分钟

Go 语言基础

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天

1 简介

1.1 什么是 Go 语言

  1. 高性能、高并发
  2. 语法简单、学习曲线平缓
  3. 丰富的标准库
  4. 完善的工具链
  5. 静态链接
  6. 快速编译
  7. 跨平台
  8. 垃圾回收

1.2 字节为什么全面拥抱 Go 语言

  1. 最初使用的 Python,由于性能问题换成了 Go
  2. C++ 不太适合在线 Web 业务
  3. 早期团队非 Java 背景
  4. 性能比较好
  5. 部署简单、学习成本低
  6. 内部 RPC 和 HTTP 框架的推广

2 入门

2.1 基础语法 - 变量

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

下面讲述 go 语言里面的变量的声明,在 go 语言里面变量的声明有两种方式,一种是通过 var name string = "" 这种方式来声明变量,声明变量的时候,一 般会自动去推导变量的类型。如果有需要,也可以显示写出变量类型。另一种声明变量的方式是使用 变量 := 值。

下面来说说常量,就是将 var 改成 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)                // initialapple

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

2.2 基础语法 - if else

接下来介绍 go 语言里面的 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")
	}
}

2.3 基础语法 - 循环

下面讲述 go 语言里面的循环,在 go 里面没有 while 循环、do while 循环,只有唯一的一 种 for 循环。最简单的 for 循环就是在 for 后面什么都不写,代表一个死循环。循环途中你可以用 break 跳出,也可以使用经典的 C 循环,就是 for l=0;l<n;l++。这中间三段,任何一段都可以省略。

在循环里面,你可以用 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
	}
}

2.4 基础语法 - switch

下面是关于 switch 分支结构,go 语言里面的 switch 分支结构看起来也和 C或者 C++ 比较类似。同样的在 switch 后面的那个变量名,并不需要括号。这里有个很大的一点不同的是,在 C++ 里面,switch case 如果不不显示加 break 的话会然后会继续往下跑完所有的 case,在 go 语言里面的话是不需要加 break 的。相比 C 或者 C++,go 语言里面的 switch 功能更强大。可以使用任意的变量类型,甚至可以用来取代任意的 if else 语句。你可以在 switch 后面不加任何的变量,然后在 case 里面写条件分支。这样代码相比你用多个 if else 代码逻辑会更为清晰。

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

2.5 基础语法 - 数组

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

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

2.6 基础语法 - 切片

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

slice 拥有像 python 一样的切片操作,比如这个代表取出第二个到第五个位置的元素,不包括第五个元素。不过不同于 python,这里不支持负数索引。

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