Go语言-1.入门指南| 青训营

140 阅读7分钟

1 语言特点

语法类似c语言;不需要引入大量经过优化的库文件。易于上手。高并发高性能。 编译很快。跨平台。有垃圾回收机制。强类型语言。

2 环境搭建

2.1 软件安装

对于以下软件,可以参考多项安装教程。本次只有第一步和第三步为新执行,VSCode已经装过。

  1. 优先在本机安装Go,本系统为Windows。下载网址:go.dev/
  2. 安装代码编辑器VSCode,下载网址:code.visualstudio.com/
  3. 在VSCode中安装Go语言扩展。 image.png

2.2 简单案例测试

需要通过实际案例判断环境是否成功搭建。

  1. 构建新项目地址【随便自定义】;
  2. 打开VSCode,并打开项目文件夹,我的项目名称为GO-EX。 image.png
  3. 新建main.go,填入hello word测试代码。
package main
import (
	"fmt"
)
func main() {
	fmt.Println("hello world")
}
  1. 初始化项目,添加go.mod文件。在VSCode中新建终端【Terminal】,出现项目根目录,执行go mod init <module_name>。未初始化会报错无法执行。本次执行的指令为go mod init example.com/gotext image.png
  2. 在终端输入go run main.go,启动main.go文件,终端输出hello world,即完成环境搭建。 image.png

2.3 函数自主补充

在编写代码过程中发现访问某些包时,函数不会自动通过.获取。因此对这部分内容进行补充。有修改过GOPATH,Go相关内容存放在D:\go下。 image.png

  1. 用户变量和系统变量中Path的添加值都改为 %GOPATH%bin。这一步修改完成后重启VSCode并没有解决问题。
  2. 在成功install all【导入go需要的所有依赖包】后,发现很多地方报错。因此参考如下链接添加go.work文件,该文件出现后,代码能够自动补充函数。

3 语法

3.1 基础语法

3.1.1 定义变量

定义变量关键字:var,一次可以定义单个或多个变量;

另一种格式:变量值 := 值;该方式自动选择数据类型。

由于Go是强类型语言,定义时必须带上变量值所属类型。【区别于python不带数据类型】

3.1.2 匿名变量

标识符为下划线“_”的变量称为匿名变量。属于标识符,仅作占位使用。

赋值后立刻释放的变量。

3.1.3 常量

使用const关键字进行定义,对于常量不能使用:=

3.1.4 案例代码

package main
import (
	"fmt"
)
func getNum()(int,int,int){
	return 1,2,3;
}
func main() {
	var f int;
	e, g := 9,10;
	s1 := "absc";
	f = 1;
	_,b,_ := getNum()
	fmt.Println(b,e,f,g,s1);
}

image.png math包能够支持数学计算

3.2 循环判断

3.2.1 if判断

GoLang的判断不需要小括号,但是需要大括号。在判断条件之前可以添加执行语句,需要用分号【;】隔开。

if 判断条件 {}

3.2.2 switch

GoLang的switch更加强大,无需添加break语句自动访问下一个case。

package main
import (
	"fmt"
	"time"
)
func main() {
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("It's before noon")
	default:
		fmt.Println("It's after noon")
	}
}

image.png

3.2.3 循环

与其它语言的循环不同,Go不支持while循环,只有for循环。

与if语句相似,for语句不使用小括号,但是使用大括号。

for 循环条件【初始条件;判断条件;操作】{}

上述循环条件有三种情况:

  1. 不写。永远为真,死循环;
  2. 只判断,不写初始条件和判断。可以看作while循环;
  3. 所有条件填写完整。同其他语言的for循环,但是不带括号。

3.2.3 案例

for j := 7; j < 9; j++ {
		fmt.Println(j)
	}

3.3 函数

3.3.1 函数定义

func [函数名](变量1 类型1, 变量2 类型2,...) (返回值){
// 返回值如果是单个值,上面的括号可以不加
    return 返回值1,返回值2,...;
}

函数接收的参数类型相同,可以只写一个类型名。

函数支持同时返回多个值,对于不需要的值,可以采用_作为匿名变量。

3.3.2 defer关键字

defer 函数调用语句【defer后面必须是函数调用】

将defer后面执行的函数推迟到外层函数执行到返回值后再执行。

3.4 数组

3.4.1 数组定义

var 数组名 [n]类型:其中,n代表数组个数。数组大小不可改变【同c语言】 赋值方式:

  1. 数组名[角标] = value 进行赋值;
  2. b := [5]int{1, 2, 3, 4, 5}

3.4.2 数组切片

类似python中取list的一部分,Golang通过固定上下界取数组一部分值。

数组名[low:hign]:包括第一个元素,不包括最后一个元素【同python类似】

切片值修改,原值也会修改;切片支持append添加元素。 案例代码

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[0:3])
	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)
	str := [4]string{"aa","bb","cc","dd"}
	str1 := str[0:2]
	str2 := str[0:3]
	fmt.Println(str1,str2)
	str2[0] = "xxx"
	fmt.Println(str,str1,str2)
}

image.png

3.4.3 make构造切片

make:内建函数,支持创建切片、动态数组。 len():数组定义时约定的长度;len(str[0,0])=0 cap():数组容量,在内存中的长度,底层长度。len(str[0,0])=5

var a [5]int
a[4] = 100
fmt.Println("len:", len(a[0:0]))
fmt.Println("cap:", cap(a[0:0]))
        
######################
结果输出:
len: 0
cap: 5

make构造切片:变量名 := make([]类型, lenth) 【lenth就是切片长度】。make会分配一个元素为0的数组并返回一个引用了它的切片。

如果想要设置容量:变量名 := make([]类型, lenth, cap)

make支持自定义切片大小。cap指的是在内存中分配的空间大小。

package main

import "fmt"

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) 
	good := []string{"g", "o", "o", "d"}
	fmt.Println(good) // [g o o d]
}

image.png

3.4.4 map

map同样可以使用make构建。变量名 := make(map[string]int)【其中,中括号内的类型代表key值类型,中括号后的类型代表value的类型】

map支持通过range遍历

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
	delete(m, "one")
	m2 := map[string]int{"one": 1, "two": 2}
	var m3 = map[string]int{"one": 1, "two": 2}
	fmt.Println(m2, m3)
}

image.png

3.4.5 range

用来遍历,和for联用

package main
import "fmt"
func main() {
	nums := []int{2, 3, 4}
	sum := 0
	for i, num := range nums {
		sum += num
		fmt.Println("index:", i, "num:", num)
	}
	fmt.Println(sum)
	m := map[string]string{"a": "A", "b": "B"}
	for k, v := range m {
		fmt.Println(k, v)
	}
	for k := range m {
		fmt.Println("key", k)
	}
}

image.png

3.5 指针与结构体

3.5.1 指针

*取值;&取地址。 定义方式:在函数中定义func demo(n *int)

3.5.2 结构体

定义结构:

type 【结构名】 struct {
	【结构体参数1】    参数类型1
	【结构体参数2】    参数类型2
}

结构体执行函数时,可以结合指针使用。

func checkPassword2(u *user, password string) bool {
	return u.password == password
}

4 库

4.1 errors

可以在函数返回值中添加error,即函数可能出现错误。支持直接使用if-else对error进行操作。

package main

import (
	"errors"
	"fmt"
)
type user struct {
	name     string
	password string
}
//函数中添加error返回值
func findUser(users []user, name string) (v *user, err error) {
	for _, u := range users {
		if u.name == name {
			return &u, nil
		}
	}
	return nil, errors.New("not found")
}
func main() {
	u, err := findUser([]user{{"wang", "1024"}}, "wang")
        //如果调用函数获取到error不为空,输出error
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(u.name)
	if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
		fmt.Println(err) 
		return
	} else {
		fmt.Println(u.name)
	}
}

4.2 strings

针对字符串相关操作,包括元素包含判断【strings.Contains()】;字符计算【strings.Count()】;strings.Split();strings.Index()等函数。

4.3 fmt

负责输出的包。

%v支持任意类型输出。%+v、%#v支持更多内容显示。支持浮点数以固定小数位数完成输出【fmt.Printf("%.2f\n",f)】

4.4 json

import包名:encoding/json 构建Json格式的结构名称需要大写第一个字母【大写字母开头】,可以自定义输出形式。【有结构体类似】

type userInfo struct {
	Name  string
	Age   int `json:"age"`
	Hobby []string
}

json中包含序列化、反序列化、拷贝等多种函数。

4.5 time

time.Now():获取当前时间; 支持Seconds();Year();Month()等函数; t.Format("2006-01-02 15:04:05")【这个时间格式好像是固定的,用于格式转换】。

4.6 strconv

实现进制转换 strconv.ParseFloat("1.234", 64)

4.7 os

os库主要还是涉及系统层面的操作,比如环境变量,cmd/shell指令等内容。