Go语言基础-基础语法 | 青训营笔记

前言

本文主要介绍Go语言的基础语法,除了上课内容外,还包括我看的其他资料以及视频。

重点内容

  • Go语言简介

  • Go语言基础

  • 开发环境

  • 基础语法

  • 标准库

知识点介绍

Go语言简介

Go是一个开源的编程语言,它很容易用于构建简单、可靠和高效的软件。

Go语言有着以下特点:

  1. 高性能、高并发

  1. 语言简单,学习曲线平缓

  1. 丰富的标准库

  1. 完善的工具链

  1. 静态链接

  1. 快速编译

  1. 跨平台

  1. 垃圾回收

Go语言基础

开发环境

  1. 官网安装Golang,目前的新版本已经可以自动配置环境变量

  1. 如果不想折腾,那直接安装Goland即可;我选择的是vscode+Go插件。这里需要注意的是在安装go相关依赖的时候可能会报错,需要在终端修改go环境参数配置

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn  # 将代理设为国内源

修改后就可以根据vscode提示安装Go Tools相关。

ps:还可以安装一个Code Runner插件,一键运行

Go的开发环境就配置完毕,接下来就可以愉快的开启Go旅程。

基础语法

基础数据类型
  • 整型

  • 浮点数

  • 复数

  • 布尔型

  • 字符串

变量
// 一般语法
var 变量名字 类型 = 表达式
// 简短变量声明
a := 100 // 只能在函数中使用
var a = 100
var a int
常量
// 一般语法
const 变量名字 类型 = 表达式
流程控制语句

循环控制语句只有for关键字,循环条件不需要括号,大括号必须放到for同一行,条件均可省略

// 死循环
for {
    fmt.Println("loop")
    break
}

for n := 0; n < 5; n++ {
    if n%2 == 0 {
        continue
    }
    fmt.Println(n)
}
// 只有终止条件
i := 1
for i <= 3 {
    fmt.Println(i)
    i = i + 1
}

条件分支语句包括 if-else 和 switch

if 7%2 == 0 {
	fmt.Println("7 is even")
} else {
	fmt.Println("7 is odd")
}
// 这里的用法与C++不同
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")
}
// Go中可以省略break
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")
}
数组

数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。因为数组的长度是固定的,因此在Go语言中很少直接使用数组。

// 不同声明方法
var a [3]int 
var a [3]int = [3]int{1, 2, 3}
a := [3]int{1, 2, 3}
a := [...]int{1, 2, 3}
切片

Slice(切片),它是可以增长和收缩的动态序列。一个slice由三个部分构成:指针、长度和容量。指针指向第一个slice元素对应的底层数组元素的地址;长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。

// 不同声明方法
var a []int 
var a []int = []int{1, 2, 3}
a := []int{1, 2, 3}
a := make([]int, 3)

切片可以使用 append 函数向切片追加元素

a = append(a, 4)
Map

哈希表是一种巧妙并且实用的数据结构。它是一个无序的key/value对的集合,其中所有的key都是不同的,然后通过给定的key可以在常数时间复杂度内检索、更新或删除对应的value。

map类型可以写为map[K]V,其中K和V分别对应key和value。map中所有的key都有相同的类型,所有的value也有着相同的类型,但是key和value之间可以是不同的数据类型。其中K对应的key必须是支持==比较运算符的数据类型,所以map可以通过测试key是否相等来判断是否已经存在。

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

m := map[string]int{
    "one": 1,
    "two": 2,
}

使用 delete 函数删除元素

delete(m, "one")
结构体

结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体。每个值称为结构体的成员。

type user struct {
	name     string
	password string
}
// 成员声明方式
a := user{name: "wang", password: "1024"}
b := user{"wang", "1024"}
c := user{name: "wang"}
c.password = "1024"
// 成员访问方式
var d user
d.name = "wang"
d.password = "1024"
JSON

JavaScript对象表示法(JSON)是一种用于发送和接收结构化信息的标准协议。

可以通过 Marshal 函数将结构体转换为JSON

type Movie struct {
    Title  string
    Year   int  `json:"released"`
    Color  bool `json:"color,omitempty"`
    Actors []string
}
data, err := json.Marshal(movies)
if err != nil {
    log.Fatalf("JSON marshaling failed: %s", err)
}
fmt.Printf("%s\n", data)
// 为了便于阅读,使用json.MarshalIndent函数
data, err := json.MarshalIndent(movies, "", "    ")
if err != nil {
    log.Fatalf("JSON marshaling failed: %s", err)
}
fmt.Printf("%s\n", data)

通过 json.Unmarshal 函数完成将JSON解码为一个结构体

var titles []struct{ Title string }
if err := json.Unmarshal(data, &titles); err != nil {
    log.Fatalf("JSON unmarshaling failed: %s", err)
}
fmt.Println(titles)
range遍历方式

利用 for-range 遍历复合数据类型

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
函数

函数声明包括函数名、形式参数列表、返回值列表(可省略)以及函数体。

func name(parameter-list) (result-list) {
    body
}

Go中函数可以返回多个值

links, err := findLinks(url)
links, _ := findLinks(url) // 可以利用_占位不需要的返回值

拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值。函数字面量的语法和函数声明相似,区别在于 func 关键字后没有函数名。函数值字面量是一种表达式,它的值被称为匿名函数(anonymous function)。

// squares返回一个匿名函数。
// 该匿名函数每次被调用时都会返回下一个数的平方。
func squares() func() int {
    var x int
    return func() int {
        x++
        return x * x
    }
}
func main() {
    f := squares()
    fmt.Println(f()) // "1"
    fmt.Println(f()) // "4"
    fmt.Println(f()) // "9"
    fmt.Println(f()) // "16"
}

参数数量可变的函数称为可变参数函数。在声明可变参数函数时,需要在参数列表的最后一个参数类型之前加上省略符号“...”,这表示该函数会接收任意数量的该类型参数。

func sum(vals ...int) int {
    total := 0
    for _, val := range vals {
        total += val
    }
    return total
}
指针

Go中指针主要用于对函数传参时,函数默认按值传递,函数内部对变量的更改不会影响函数外,如果需要改变,需要通过指针传递

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

func add2ptr(n *int) {
	*n += 2
}

func main() {
	n := 5
	add2(n)
	fmt.Println(n) // 5
	add2ptr(&n)
	fmt.Println(n) // 7
}

标准库

fmt

包实现了类似C语言printf和scanf的格式化I/O。

import "fmt"

s := "hello"
n := 123
p := point{1, 2}
fmt.Println(s, n) // hello 123
fmt.Println(p)    // {1 2}

fmt.Printf("s=%v\n", s)  // s=hello
fmt.Printf("n=%v\n", n)  // n=123
fmt.Printf("p=%v\n", p)  // p={1 2}
fmt.Printf("p=%+v\n", p) // p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}

f := 3.141592653
fmt.Println(f)          // 3.141592653
fmt.Printf("%.2f\n", f) // 3.14
time

包含时间处理的函数。

import (
	"fmt"
	"time"
)

now := time.Now()

t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
fmt.Println(t)    // 2022-03-27 01:25:36 +0000 UTC

t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)
diff := t2.Sub(t)
fmt.Println(diff)                           // 1h5m0s
fmt.Println(diff.Minutes(), diff.Seconds()) // 65 3900
strconv

strconv包实现了基本数据类型和其字符串表示的相互转换。

import (
	"fmt"
	"strconv"
)

f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f) // 1.234

n2, _ := strconv.Atoi("123")
fmt.Println(n2) // 123
env

os包提供了操作系统函数的不依赖平台的接口。

exec包执行外部命令。它包装了os.StartProcess函数以便更容易的修正输入和输出,使用管道连接I/O,以及作其它的一些调整。

import (
	"fmt"
	"os"
	"os/exec"
)

// go run example/20-env/main.go a b c d
fmt.Println(os.Args)           // [/var/folders/8p/n34xxfnx38dg8bv_x8l62t_m0000gn/T/go-build3406981276/b001/exe/main a b c d]
fmt.Println(os.Getenv("PATH")) // /usr/local/go/bin...
fmt.Println(os.Setenv("AA", "BB"))

// 用于使用给出的参数执行第一个参数指定的程序
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput() 
if err != nil {
    panic(err)
}
fmt.Println(string(buf)) // 127.0.0.1       localhost

总结

收获

本文主要介绍了Go语言的基本语法,与C++等语言有相类似的地方,但是也有很多的区别,比如变量类型后置等都不太习惯。如果有其他语言的基础,Go的基本语法还是比较容易理解的,不过还是要勤加练习才能熟练掌握。

问题

对一些标准库和API接口还是比较陌生,后续通过项目实战。

引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值