GO语言基础语法 | 青训营笔记

75 阅读5分钟

Go语言基础

优势

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

字节使用Go的原因

  1. 最初使用Python,由于性能差换成了Go
  2. C++不适合在线的Web业务
  3. Java在早期团队的普及率不高
  4. GO性能更好
  5. 部署简单、学习成本低
  6. 内部RPC和HTTP框架的推广

安装与配置环境

  1. go.dev 官网下载go1.20.4.windows-amd64.msi安装

2.配置环境变量 1-1.png

3.安装完毕 1-2.png 4.安装ide,安装VScode的go插件

1-3.png

变量

func main() {
	name := "Go Developers"
	var a, b, c int = 1, 2, 3 //var 变量名称 变量类型
	//d := true                 //;=快速定义

	//e := "hello" + "world" //+表示连接
}

选择结构



	var username string
	var sno int
        
	fmt.Scanln(&username, &sno)
	switch username {
	case "hjq":
		if sno == 1 { //大括号必须同行,而且必有不能单行省略
			fmt.Println(username, " certificate accepted")
		} else {
			fmt.Println("warring...Unauthorized")
		}
	case "hhq":
		if sno != 1 {
			fmt.Println(username, " certificate accepted")
		} else if sno == 1 {
			fmt.Println("warring...Unauthorized")
		}
	default:
		fmt.Println("attack!")
		break
	}


The if...else if...else Statement

if语句可以后接一个可选的else if...else语句,这种类型的结构可以很方便的用来对多个条件进行测试。

使用此结构,需要注意以下几个方面

if语句后可以不接else语句,或者接一个else语句,并且else语句只能跟在else if语句后面。

if语句可以接零个,或多个else if语句,else if语句必须在else语句前面。

一旦匹配上else if语句,剩余的条件将不会验证。

循环结构


func main() {
	i := 1
	for { //只支持for循环
		fmt.Println("loop")
		break
	}
	for j := 1; j < 5; j = j + 2 {
		if j == 1 {
			continue
		}
		fmt.Println(j)
	}
	for i <= 3 {
		fmt.Println(i)
		i++
	}

}

与多数语言不同的是,Go语言中的循环语句只支持 for 关键字,而不支持 while 和 do-while 结构,关键字 for 的基本使用方法与C/C++中非常接近:

使用循环语句时,需要注意的有以下几点:

  • 左花括号{必须与 for 处于同一行。
  • Go语言中的 for 循环与C语言一样,都允许在循环条件中定义和初始化变量,唯一的区别是,Go语言不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方式来初始化多个变量。
  • Go语言的 for 循环同样支持 continue 和 break 来控制循环,但是它提供了一个更高级的 break,可以选择中断哪一个循环

切片

package main

import (
	"fmt"
)

func main() {
	s := make([]string, 3)
	s[0] = "a"
	s[1] = "b"
	s[2] = "c"
	fmt.Println("get:", s[0], "len:", len(s))

	s = append(s, "e", "f")
	fmt.Println(s)

	c := make([]string, len(s))
	copy(c, s)
	fmt.Println(c) //a b c d e f

	//切片
	fmt.Println(c[2:5]) //2到5不包括5
	fmt.Println(c[:5])  //省略从头
	fmt.Println(c[:])
	exercise := []string{"h", "i", "g", "h", "s"}
	fmt.Println(exercise)
	exercise3 := []string{"h", "i", "gs", "hsa", "s"}
	fmt.Println(exercise3)

	//映射
	m := make(map[string]int)
	m["one"] = 1
	m["two"] = 2

	fmt.Println(m, len(m), m["one"], m["unknown"])

	r, ok := m["unknown"]
	fmt.Println(r, ok)

	m2 := map[string]int{"mon": 1, "tue": 2, "wen": 3}
	fmt.Println(m2)

}

切片是围绕着动态数组的概念来构建的,它跟数组类似,是用于管理数据集合的一种数据结构。

数组一旦创建就不能更改其长度和类型,而切片就不同,切片可以按需自动增长和缩小,增长一般使用内置的 append 函数来实现,而缩小则是通过对切片再次进行切割来实现。

切片内部实现

切片对底层数组进行了抽象,并提供相关的操作方法,其内部包含3个字段:指向底层数组的指针、切片访问的元素的个数(即长度)、切片运行增长到的元素个数(即容量)。

切片的创建有两种方式:一种是使用 make 函数来创建,另一种是使用字面量方式创建。

range

	nums := []int{2, 3, 4}
	sum := 0
	for i, num := range nums {
		sum += num

		Println("index", i, "num", num)
	}
	Println(sum)
	m3 := map[string]string{"a": "A", "b": "B"}
	for k, v := range m3 {
		Println(k, v)
	}
	for k := range m3 {
		Println("key", k)
	}

函数与指针

func add1(n int) {
	n += 2
}
func add2(n *int) {
	*n += 2
}

func main() {
	Println(add(1, 2))
	v, ok := exists(map[string]string{"a": "A", "b": "B"}, "a")
	Println(v, ok)
	N := 2
	add1(N)
	Println(N) //没改变
	add2(&N)
	Println(N)

}

指针在Go语言中可以被拆分为两个核心概念:

  • 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。

  • 切片,由指向起始元素的原始指针、元素数量和容量组成。

受益于这样的约束和拆分,Go语言的指针类型变量即拥有指针高效访问的特点,又不会发生指针偏移,从而避免了非法修改关键性数据的问题。同时,垃圾回收也比较容易对不会发生偏移的指针进行检索和回收。

结构


type user struct {
	name     string
	password string
}

func main() {
	a := user{name: "hjq", password: "5050"}
	b := user{"hhq", "8080"}
	b.resetPassword("8089")
	Println(checkPassword(&b, "8080"))

	Println(a, b)

}

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

func (u *user) resetPassword(password string) {
	u.password = password
}

go的结构使用很灵活,在定义时的代码量就大大降低,灵活使用可以大大降低了定义的成本,可以将结构体作为参数,调用结构体中的成员变量进行操作,类似类的成员变量。