GO语言学习 | 青训营笔记

107 阅读5分钟

1Go语言简介 由于Go语言有语法简单、高性能等特点,因此国内外各大公司如谷歌、腾讯、字节等都在使用,特别是字节全面拥抱Go,原因是最初因性能问题将Python换成Go,而Go学习简单,性能高,且部署简单。总的来说Go语言特性如下:

语法简单、学习曲线平缓

高性能、高并发

丰富的标准库

完善的工具链

静态链接

快速编译

跨平台

垃圾回收

个人而言,因我是C++出身,对C++复杂的语法感到麻木,因此特别喜欢Go语法简单、上手快的特点,几小时就能上手,再加上Go天生高并发,有丰富标准库等特点,几近完美,因此建议大家学下Go

2入门 2.1开发环境 本地编译环境:Golang、VSCode

云端开发环境:gitpod

2.2基础语法

Hello World

package main import ( "fmt" ) func main() { fmt.Println("hello world") } 第一行代表属于main包,它是程序入口包,import导入fmt包,并再main函数中调用其Println函数。使用go build或go run编译或编译并运行代码

变量 go是强类型,变量都有类型,声明变量时常用方式:

var varname type = value:需var关键字且类型放后面 varname := value:会自行推到类型 字符串 go的strings包有很多常用函数:contains判断是否包含另一字符串、count字符串计数、index查找字符串位置、join连接多字符串、repeat重复多个字符串、replace替换字符串

字符串格式化 fmt包中有很多字符串格式化相关的方法,但常用“%v”打印任意类型变量,不需区分类型,“%+v”和“%#v”则更详细

数字解析 字符串和数字间转换通过strconv包的函数,Atoi表示字符串转数字相反则Itoa

if else判断 if后无括号,写括号的话编辑器会自动去掉,且后面必须接大括号

switch switch后变量名无括号,case中不加break,且可以使用任意变量类型,当判断较多时可用switch完全替代if else

for循环 只有唯一的for循环,for中三语句任何语句都可省略且也没括号,循环中可用break或continue跳出或继续循环

range 常用range快速遍历数组、slice、map等,返回索引和值,可用“_”忽略索引

数组 类似其他语言中固定长度数组,实际很少使用,更多使用切片

切片 slice长度不固定,用make创建,append时自动扩容,可像python中切片一样截取

map 实际使用最频繁的数据结构,用make创建,常用val,ok:=m[key]写法,通过判断ok判断是否存在key对应的val

函数 参数和返回值类型后置,支持返回多个值,实际代码中几乎所有函数返回两个值:结果和错误信息,注意参数是都值传递,若想修改参数,需传递指针。首字母大写表示公共函数,类似C++中public函数,可包外访问

指针 类似C/C++指针,但操作有限,指针主要用途是对传入参数修改

结构体 结构体初始化时需传入每个字段初始值,也可键值对的方式初始化,通常用结构体的指针作为参数,既能修改结构体又能避免结构体的拷贝开销,字段首字母大写表示公开字段,类似C++中public成员

结构体方法 再函数名前带上结构体参数和括号,就实现类似其他语言中的类成员函数

错误处理 go常见做法是再传递结果的返回值的基础上,新增一个传递错误信息的返回值,这样能清晰知道哪个函数出错,且能用简单的if else处理错误

defer处理 go中为避免资源泄露,需用defer手动关闭资源,会在函数运行结束后执行

json处理 对已有结构体,保证每个字段首字母大写,是公开字段,就能用marshaler序列化变成json字符串,unmarshaler反序列化,可用json tag修改输出结果的字段名

时间处理 time包包含时间处理各种函数,用Date构造带时区时间,Now获取当前时间

进程处理 os包包含进程处理,Args得到命令参数,Getenv读环境变量,Command执行命令

3实战项目 实战项目主要是为巩固基础语法,并且是逐步开发、快速迭代改进,很有参考价值

猜数字游戏 设置随机数种子,随机生成100以内的数,提示用户输入,并和用户输入的数据比大小,根据大小提示信息,不断循环,最终猜正确才退出循环。通过该例子巩固变量循环、函数控制流和错误处理等知识


import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
)

func main() {
	maxNum := 100
	rand.Seed(time.Now().UnixNano())
	secretNumber := rand.Intn(maxNum)
	// fmt.Println("The secret number is ", secretNumber)

	fmt.Println("Please input your guess")
	reader := bufio.NewReader(os.Stdin)
	for {
		input, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("An error occured while reading input. Please try again", err)
			continue
		}
		input = strings.TrimSuffix(input, "\n")

		guess, err := strconv.Atoi(input)
		if err != nil {
			fmt.Println("Invalid input. Please enter an integer value")
			continue
		}
		fmt.Println("You guess is", guess)
		if guess > secretNumber {
			fmt.Println("Your guess is bigger than the secret number. Please try again")
		} else if guess < secretNumber {
			fmt.Println("Your guess is smaller than the secret number. Please try again")
		} else {
			fmt.Println("Correct, you Legend!")
			break
		}
	}
}