Go 语言入门指南:基础语法和常用特性解析|豆包MarsCode AI刷题

51 阅读7分钟

简介

什么是Go语言(Go的特点)

Google产品,一门通用型计算机编程语言

  1. 高性能、高并发

    1. 媲美C++、Java性能
    2. 使用标准库或任意基于标准库的第三方库,即可开发高并发的应用程序
  2. 语法简单、学习曲线平缓

    1. 语法风格类似于C语言,并在其基础上进行简化
  3. 丰富的标准库

  4. 完善的工具链

  5. 静态链接

    1. Go中所有的的编译结果默认都是静态链接的,只需要拷贝编译后唯一的可执行文件,不需要附加任何东西就能部署运行
    2. 在线上的容器环境下运行,镜像的体积可以控制的非常小,部署非常方便快捷
  6. 快速编译

  7. 跨平台

  8. 垃圾回收

    1. 无需考虑内存的分配释放
    2. 只需专注于业务逻辑

入门

开发环境

  1. 安装Go语言

    go.dev/

    镜像:

    studygolang.com/dl

    https://goproxy..cn/

  2. 配置Go的集成开发环境

    VS code / Goland

基础语法

关键字

    break        default      func         interface    select
    case         defer        go           map          struct
    chan         else         goto         package      switch
    const        fallthrough  if           range        type
    continue     for          import       return       var

运算符

  1. 算术运算符

    +
    -
    *
    /
    %取余
  2. 关系运算符

    ==判断是否相等
    判断是否不相等
    判断左边是否大于右边
    <判断右边是否大于左边
    判断左边是否大于等于右边
    判断左边是否小于等于右边
  3. 逻辑运算符

    &&and
    !not
  4. 位运算符

    &
    异或,二进位相异结果为1
    <<向左移位
    >>向右移位
  5. 赋值运算符

    =
    +=
    -=
    *=
    /=
    %=
    << =左移后赋值
    >> =右移后赋值
    &=按位与后赋值
    =
    ^=按位异或后赋值

下划线

  • import 中,表示仅引用该包中的某个函数
  • 在函数中,表示忽略这个变量
  • 在函数中,也可表示为占位符

hello world

package main // 程序入口文件

import (
	"fmt"
)// 导入标准库的format包,用于输入输出字符串,格式化字符串

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

如果运行这个程序

go run 01-hello/main.go

编译这个程序

go build 01-hello/main.go 输入 ./main 就可以运行

变量

常见的变量:字符串、整数、浮点型、布尔型

  • 变量适用于存储数据,go中每一个变量都有自己的类型
  • Go语言中字符串是内置类型,可以直接通过加号去拼接
  • go中的变量必须经过声明后才能使用,同作用域内不支持重复声明
  • 3种变量声明方式,用关键字var
  • 常量的声明方式

常量

  • 常量相对于变量,是不变的值
  • 常量用const 关键字声明,且常量在定义的时候必须赋值
  • iota 是go中的常量计数器,只能在常量的表达式中使用
package main

import (
	"fmt"
	"math"
)

func main() {

	var a = "initial" // 声明变量,一般会自动推导类型。类型为string,初始值为"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" // 声明常量,不可修改,go中的常量没有确定的类型,通过上下文自动确定类型
	const h = 500000000
	const i = 3e20 / h
	fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}

if-else

  • 写法与C++类似,不同的是if后面没有括号
  • 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")
	}
}

循环

  • 只有唯一的for循环
  • for {...} 代表一个死循环
  • continue 继续循环,break跳出循环
package main

import "fmt"

func main() {

	i := 1
	for {
		fmt.Println("loop")
		break
	}// 无限循环,break跳出循环
	for j := 7; j < 9; j++ {
		fmt.Println(j)
	}// 有限循环,j的作用域只在for循环中

	for n := 0; n < 5; n++ {
		if n%2 == 0 {
			continue
		}
		fmt.Println(n)
	}
	for i <= 3 {
		fmt.Println(i)
		i = i + 1
	}
}

switch分支

  • switch后面不需要括号
  • 在switch内部不需要通过break跳出分支,运行其中一个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")
	}
}

数组array

  • 是一个具有编号,且长度固定的元素序列
  • 数组通过下标进行访问,下标从0开始,最后一个下标是len-1
  • 2种数组声明方式
  • 数组是值类型,赋值和传参数回复制整个数组,而不是指针,所以改变拷贝的值,不会改变自身的值
package main

import "fmt"

func main() {

	var a [5]int // 声明数组,长度为5,初始值为0
	a[4] = 100
	fmt.Println("get:", a[2])//读取数组元素下标2的元素,下标从0开始
	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)
}

切片slice

  • 不同于数组,是一个可变长度的数组,可以任意时刻更改长度
  • 用make创建一个切片
  • 用append追加元素
  • 用copy拷贝数组
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]
}

map

  • 哈希/字典
  • 使用最频繁的数据结构
  • 用make创建一个空map,需要两个类型(key和value的类型)
  • 通过map[key]=value 写入kv对
  • 通过map[key] 读取kv对
  • 通过delete(map,key) 删除kv对
  • go中的map是无序的,遍历的时候不会按字母顺序,也不会按插入顺序输出,而是随机输出
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

	r, ok := m["unknow"] // ok用于判断key是否存在
	fmt.Println(r, ok) // 0 false

	delete(m, "one")

	m2 := map[string]int{"one": 1, "two": 2}
	var m3 = map[string]int{"one": 1, "two": 2}
	fmt.Println(m2, m3)
}

range

  • 对于一个slice或是map,可以使用range进行快速遍历
  • 对于数组,返回两个值(索引,对应位置的值)
  • 对于map,返回两个值(key,value)
package main

import "fmt"

func main() {
	nums := []int{2, 3, 4}
	sum := 0
	for i, num := range nums {
		sum += num
		if num == 2 {
			fmt.Println("index:", i, "num:", num) // index: 0 num: 2
		}
	}
	fmt.Println(sum) // 9

	m := map[string]string{"a": "A", "b": "B"}
	for k, v := range m {
		fmt.Println(k, v) // b 8; a A
	}
	for k := range m {
		fmt.Println("key", k) // key a; key b
	}
}

函数

  • 不需要申明原型
  • 可以不定变参
  • 可以返回多个值

指针

  • 主要用于对传入的参数进行修改
  • go中的指针不能偏移和运算
  • 每个变量都有一个地址,&变量 表示对变量进行 取地址 的操作

结构体

  • go中没有 类 的概念
  • 带类型的字段的集合
  • 可以通过typestruct 关键字定义结构体
  • 只有当结构体实例化的时候,才会分配内存
  • 结构体本身也是一种类型,可以使用var 关键字申明结构体类型

错误处理

字符串操作

  • Contains 判断一个字符串是否包含另一个字符串
  • Count 字符串计数
  • Index 查找某个字符串的位置
  • Join 连接多个字符串
  • Repeat 重复多个字符串
  • len 获取字符串的长度

字符串格式化

  • fmt.Println(, , , ) 打印多个变量并且换行
  • fmt.Printf("s=%v\n",s)//{1 2} %v打印任意类型变量
  • fmt.Printf("s=%+v\n",s)//{x:1 y:2} %+v打印更加详细的结果
  • fmt.Printf("s=%#v\n",s)//main.point{x:1 y:2} %#v打印任意类型变量
  • fmt.Printf("%.2f\n", f) 打印保留两位数的浮点数

JSON处理

  • 对已有的结构体,只需要保证结构体的每行字段的第一个字母是大写
  • 这个结构体就能通过json.Marsha 进行数列化
  • 数列化之后会变成buf数组,打印时要加上string(buf) 才能打印

时间处理

  • time.Now() 快速获取当前时间

数字解析

  • 包:strconv
  • ParseFloat ParseInt 解析字符串
  • Atoi 快速将十进制字符串转化为十进制数字
  • Itoa 将十进制数字转化为十进制字符串

进程信息

  • os.Args 获取进程在执行的命令行参数
  • os.Getenv/os.Setenv获取/写入环境变量
  • exec.Command 快速启动程序,并获取其输入输出