初识Go(补档)| 青训营

113 阅读8分钟

Golang入门

Golang,一门由Google开发的后端语言,会无端联想到由微软开发的前端语言TypeScript,毕竟是两家知名企业。欸嘿嘿~

内容主要根据课程来,主要是基础的东西,连篇累牍,难免有背书之嫌,尽量将知识总结全,只希望不犯下基本错误,惹贻笑大方。

Go语言的基本特征:

高性能和高并发

Go语言在性能方面媲美C++和Java,并且具有优秀的并发支持。它采用了轻量级的线程goroutine(一个goroutine只占2KB的内存)和通信机制(channel,下次课会有详细介绍),可以方便地实现并发编程,提高程序的响应能力和并发处理能力。与它丰富的标准库相关,不需要去费心寻找性能优化完善的第三方库,使用标准库和基于标准库的第三方库即可。

简洁的语法

Go语言继承了C语言的语法风格,易于学习和阅读。同时去掉了一些语法元素,如只保留了for循环一种循环,省去表达式括号等,使得代码更加容易上手。

ps:刷了几遍题确实是这样。写代码比较顺,主要时类型和规范这两方面不需要考虑太多,写起来就快多了(本小白的体验是这样,比较肤浅还,日后应该会随着接触深入有新的看法)

丰富的标准库

Go语言提供了丰富而稳定的标准库,涵盖了各个领域。这些标准库具有良好的性能和可靠性,利于实现开发者开发过程的稳定性。

强大的工具链

Go语言提供了一套完善的工具链,包括编译器、调试器、测试工具、性能分析器等,可以帮助开发者进行开发、测试、调试和优化工作。 em,用的还是之前写代码的Vscode插件,暂时还没找太多插件,安利一下caplock+,很好的效率提升工具。

静态编译和跨平台支持

Go语言支持静态链接,可以将程序编译为独立的可执行文件,方便部署和分发,不需要像java和C添加后缀及附属文件。同时,Go语言具有良好的跨平台支持,可以在不同操作系统上进行开发和部署,也可以在Android os应用开发上发挥作用,且无需修改或重新编译代码。

垃圾回收

Go语言采用了自动垃圾回收机制(Garbage Collection),可以自动管理内存的分配和释放,减轻了开发者的负担,并有效地避免了内存泄漏和空指针等问题。

go语言的应用优势:

主要是因为python随用户体量增长性能下滑以及库版本问题,团队非Java背景,在使用Go语言优化性能后RPC和HTTP框架推广,go语言也为业界所广泛接纳

开发环境

vscode作为一个编辑器,但是适应性非常强,而且是一款免费软件,需要配置好文件,而且通过vscode的扩展,我能够方便地获得实用的,就没有去专门下载GoLand,沿用vscode。

go语言基础语法:

hello world

启蒙

package main //声明了当前文件所属的包是 main,表示这是一个可执行程序的入口点。
import{
“fmt”}//导入标准库中的fmt包
func main(){
fmt.Println("hello world")
}//创建函数

变量的声明

在Go语言中,可以使用关键字var来声明变量,并且可以同时声明多个变量。例如:

var a string = "" var b int = 5

或者可以简化为: var a = "" var b = 5

如果变量的初始值已经明确,还可以进一步简化为:

a := ""
b := 5

条件语句:

在Go语言中,条件语句需要以关键字if开头,然后是条件表达式,不需要括号。(通常写在一行,如果条件比较长可使用断行进行分隔)

if condition {
  // 执行条件为真时的代码
} else {
  // 执行条件为假时的代码
}

switch语句,case后面可以带值,可以是逗号分隔的多个表达式,可为变量也可函数,常量值不能重复出现在case中

循环语句:

在Go语言中,可以使用关键字for进行循环控制。例如:

go
for i := 0; i < 10; i++ {
    // 循环体
}

break和continue用于在循环中进行控制流的跳转。

切片(slice):

切片是Go语言中一种灵活且强大的数据结构,它可以动态地增长和收缩。切片使用类似数组的语法,但长度可以不固定。切片的声明方式如下:

var s []int`

切片可以通过append函数添加元素,并且会自动扩容。

s := []int{1, 2, 3}
s = append(s, 4) // 添加元素4

使用make函数创建切片:

s := make([]int, 0, 5) // 创建一个长度为0,容量为5的切片

哈希表和字典(map)

在Go语言中,可以使用map关键字来声明哈希表或字典。map是一种无序的键值对集合。声明和初始化一个map的示例如下:

m := make(map[string]int)
m["key1"] = 1
m["key2"] = 2

函数:

在Go语言中,可以使用关键字func来声明函数。函数的参数和返回值都需要指定类型。例如:

go
func add(a int, b int) int {
    return a + b
}

指针:

指针是一个变量,它存储了另一个变量的内存地址。通过指针,我们可以直接访问到存储在该内存地址上的值。在Go语言中,可以使用&操作符来获取变量的地址,使用*操作符来获取指向该地址的值。指针常用于传递数据的地址,以减少复制数据的开销,并允许在函数中修改原始变量的值。

例如,假设有一个整数变量num,我们可以创建一个指向它的指针并将其赋值给另一个变量,如下所示:

num := 42
ptr := &num

在这里,&num获取了变量num的地址,然后将该地址赋值给了ptr变量。现在,通过ptr指针,我们可以访问到num变量的值。

结构体:

结构体是一种用户自定义的数据类型,它由一组字段组成,每个字段都有自己的类型和名称。结构体用于表示实体的集合,可以将多个相关的数据字段组合在一起形成一个更大的数据结构。

下面是一个简单的结构体例子:

type Person struct {
    Name string
    Age  int
}

在这个例子中,我们创建了一个名为Person的结构体,它有两个字段:NameAge。每个字段都有自己的类型和名称。

我们可以通过实例化结构体来创建结构体变量,并为其字段赋值。例如:

person := Person{
    Name: "Peelwr",
    Age: 30,
}

在这里,我们使用Person{}语法创建了一个Person结构体变量,并为其NameAge字段赋值。现在,我们可以通过person.Nameperson.Age来访问结构体变量的字段值。

此外,结构体还可以定义方法,以便操作和处理结构体数据。方法是与特定类型关联的函数。通过使用方法,我们可以在结构体上执行各种操作。

错误处理

在Go语言中,错误处理是一种重要的编程模式。通常情况下,函数会返回两个值:一个结果值和一个错误值。错误值类型为error,它是一个接口类型。可以使用errors包来引入错误处理机制。

在处理错误时,通常会使用if err != nil语句进行判断。如果错误不是nil,表示函数执行过程中出现了错误,需要进行相应的错误处理逻辑。 以下是一个示例代码,展示了如何使用错误处理机制:

package main
import ( "errors" "fmt" )
// divide 函数接收两个整数 a 和 b,返回 a 除以 b 的结果和错误值 
func divide(a, b int) (int, error) { // 如果 b 等于 0,则返回一个错误,表示除以零的操作 
if b == 0 {
return 0, errors.New("division by zero") 
} 
// 返回 a 除以 b 的结果和 nil,表示没有错误发生 return a / b, nil }
func main() { // 调用 divide 函数计算 10 除以 2 的结果 
result, err := divide(10, 2) 
if err != nil { // 如果发生错误,则打印错误信息 
fmt.Println("Error:", err) } 
else { // 如果没有发生错误,则打印结果 
fmt.Println("Result:", result) } 
}

在上面的除法代码中,如果除数为 0,则会发生错误,通过检查错误值是否为 nil 来判断是否发生了错误,并打印错误信息或计算结果。

题外:C++异常捕捉与Go的对比

本人的C++结课作业恰好就是C++制作带符号的大整数计算器,其中除法的异常状态需要进行捕获,这里把所使用的代码贴在这里作比较讲解:

需要声明#include <exception>来使用与异常相关的函数, 继而创建Error 类,自定义异常类型,并使用快捷方法来获取错误信息。

class Error : public std::exception {
public:
    explicit Error(const char* message) : msg_(message) {}//字符指针类型
    explicit Error(const std::string& message) : msg_(message) {}//字符串类型
    virtual ~Error() throw () {}//虚构类型
    const char* what() const noexcept override {//重写what函数,c风格转出,指向错误信息
    return msg_.c_str();
    }
    //获取message 信息
    std::string getMessage() const {
        return msg_;
    }
private:
    std::string msg_;
};

在实际使用中,可以通过抛出 Error 类的实例来表示发生的错误,并通过捕获异常进行错误处理。具体格式如if condition throw Error(),并在之后使用除法代码块时通过如下代码实现异常捕获

try
{
//代码块}
catch (Error& e) {
        cerr << "Error:" << e.getMessage() << endl;
    }

在输入异常时就会捕捉到并提示异常信息。 有点繁琐~

在Go语言中,通过自定义错误类型和错误处理机就能达到类似的效果(需要引入errors包先)

// 自定义一个错误类型 
type MyError struct { 
Msg string 
} 
// 实现 Error 接口的 Error 方法 
func (e *MyError) Error() string { 
return e.Msg 
}

这样一看就简洁多了~, 之后还会再根据这点再比对思考下go语言的特性

字符串操作:

Go语言中使用fmt包进行字符串格式化操作。比较多,需要记忆好以方便使用,具体的话我参考了这篇文章学习

Go语言的%d,%p,%v等占位符的使用 - 简书 (jianshu.com)

JSON处理:

Go语言提供了encoding/json包来处理JSON数据。可以使用json.Marshal函数将Go对象序列化为JSON字符串,使用json.Unmarshal函数将JSON字符串反序列化为Go对象。

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    person := Person{
        Name: "John",
        Age:  30,
    }

    // 序列化为 JSON 字符串
    jsonBytes, err := json.Marshal(person)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    jsonString := string(jsonBytes)
    fmt.Println(jsonString)

    // 反序列化为 Go 对象
    var newPerson Person
    err = json.Unmarshal([]byte(jsonString), &newPerson)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Println(newPerson.Name)
    fmt.Println(newPerson.Age)
}

时间处理:

Go语言中提供了time包用于时间相关的操作。可以使用time.Now函数获取当前时间,然后可以进行格式化、计算等操作。time.date构造一个带时间的,format格式化时间,

currentTime := time.Now()
formattedTime := currentTime.Format("2006-01-02 15:04:05")

使用time.parse解析字符串获取时间

timeString := "2021-07-25 10:30:00"
parsedTime, err := time.Parse("2006-01-02 15:04:05", timeString)

数字解析

主要记录和补充一些常用的函数

strconv.ParseInt():

这是一个用于将字符串转为整数的函数。它的语法是:

func ParseInt(s string, base int, bitSize int) (i int64, err error)
n1,_=strconv.ParseInt(s string, base int, bitSize int)

s 是要转换的字符串。 base 是进制数,例如 2、8、10 或 16。如果设置为 0,则根据字符串的前缀来确定进制数("0x" 表示十六进制,"0" 表示八进制,否则默认为十进制)。 bitSize 是结果整数的位大小,可以是 0、8、1632 或 64。返回的整数类型将根据这个参数确定。

sprintf():

这是一个用于格式化字符串的函数。它的语法是: func Sprintf(format string, a ...interface{}) format 是格式化字符串,其中包含占位符 % 和其他文本。 a ...interface{} 是可变参数,用于替格式化字符串中占位符。

atoi():

这是一个用于将字符串转换为整数的函数。它语法是: func Atoi(s string) (int, error) s 是要转换的字符串。 与 strconv.Parse() 不同,atoi() 函数会自动识别字符串中的数字,并返回相应的整数值如果字符串无法换为整数,则会返回错误。 没有转换成功将会变为默认值。 例如hello转为整数会转为0

进程信息:

记录一些常见的函数,这些函数基本都是要在网页端见面的,嗯,得做好功课

Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国 (studygolang.com)

os.Args:这是一个字符串切片,包含程序启动时传递给命令行的参数。切片第一个元素是程序的名称,后续元素是传递给程序的参数。

os.Getenv(key string) string:这个函数用于获取指定环境量的值。它接受一个字符串参数 key表示要获取的环境量的名称,并返回该环境变量的值作为字符串。如果环境变量不存在,则返回空字符串。

os.Setenv(key, value string) error:这个函数用于设置指环境变量的值。它接受两个字符串参数 key 和 value,分别表示要设置的环境变量名称和值。如果设置成功,函数返回 nil;否则,返回一个非空的错误对象。

结语

需要熟练基础的知识,使用时得有确切的印象,通过刷题和写项目以提升代码能力,这方面的工作做得不够多所以导致无法对知识点做出适如其分的判断。尤其关于JSON,进程信息这类有关网页项目的,接触的还是过于少,只能一知半解的记录下一些函数,可见对于实际应用还是经验不足,需要学着走起路。