【Go语言快速上手】第一部分:Go 语言基础

引言

在当今快速发展的技术世界中,选择合适的编程语言对于开发者来说至关重要。Go 语言,自 2009 年由 Google 推出以来,凭借其简洁、高效和强大的并发处理能力,迅速在开发者社区中获得了广泛的认可和喜爱。Go 语言的设计哲学是“少即是多”,它摒弃了复杂的语法和冗余的特性,致力于提供一种简单而强大的编程体验。

Go 语言的历史

Go 语言的诞生源于 Google 对现有编程语言的不满。在 2000 年代初期,Google 面临着大规模分布式系统开发的挑战,而当时的主流语言(如 C++ 和 Java)在开发效率、编译速度和并发处理方面存在诸多不足。为了解决这些问题,Google 的三位资深工程师——Robert Griesemer、Rob Pike 和 Ken Thompson(Unix 和 C 语言的共同创始人)——于 2007 年开始设计一门新的编程语言,这就是 Go 语言的雏形。

2009 年,Go 语言正式对外发布,并迅速吸引了全球开发者的关注。它的设计目标是成为一种适合大规模系统开发的语言,同时保持简洁性和高效性。Go 语言的诞生不仅填补了编程语言领域的空白,也为现代软件开发带来了新的思路和工具。

Go 语言的特点与优势

  • 简洁高效:Go 语言的语法清晰简洁,易于学习和使用。它的编译速度极快,执行效率高,使得开发过程更加流畅,产品迭代更加迅速。
  • 并发编程:Go 语言内置了 goroutine 和 channel,使得并发编程变得简单而直观。开发者可以轻松地编写出高效的并发程序,充分利用多核处理器的计算能力。
  • 垃圾回收:Go 语言拥有自动垃圾回收机制,有效管理内存,减少内存泄漏的风险,让开发者能够更专注于业务逻辑的实现。
  • 丰富的标准库:Go 语言的标准库功能全面,涵盖了网络编程、加密解密、数据库操作等多个领域,为开发者提供了强大的支持。

学习 Go 语言的意义

  • 云计算和微服务:随着云计算和微服务架构的普及,Go 语言因其出色的性能和简洁的并发模型,成为了构建云服务和微服务的理想选择。
  • 新兴技术:在区块链和人工智能等新兴技术领域,Go 语言也展现出了其独特的优势,成为了开发这些前沿技术的热门语言。
  • 职业发展:掌握 Go 语言不仅能够提升个人的技术竞争力,还能够为职业发展开辟更广阔的道路。无论是初创公司还是科技巨头,对 Go 语言开发者的需求都在不断增长。

1. Go 语言基础

1.1 环境搭建

首先,开始 Go 语言编程需要先完成环境的安装与配置。

Go 语言的安装和环境变量配置

下载和安装 Go 语言 SDK

  1. 访问 Go 官网 下载对应操作系统的安装包。(如果访问下载比较慢可以去下面的镜像站:阿里云 GO SDK
  2. Windows 系统运行 .msi 安装包,Mac 用户使用 .pkg,Linux 系统可以通过 tar.gz 手动解压。
  3. 按照安装指南完成安装。

配置环境变量 (GOROOT, GOPATH)

  • GOROOT: 指定 Go 语言的安装路径。
  • GOPATH: 指定 Go 代码的工作目录,通常包含 src(源代码)、bin(可执行文件)和 pkg(编译缓存)。

这里建议,安装完go语言后,将其目录下的src(源代码)、bin(可执行文件)和 pkg(编译缓存),复制一份到代码工作目录,这个目录根据自己的需求写在哪里都行,如下图:

在这里插入图片描述

随后我们将项目代码也写到这个路径下。

之后,我们将其加到环境变量中:

在这里插入图片描述

之后我们在Goland中的设置中设置好GOROOT与GOPATH即可:

在这里插入图片描述
在这里插入图片描述

选择合适的 IDE 或编辑器

  • GoLand(JetBrains 出品,强大的 Go 语言 IDE)
  • VSCode + gopls 插件(轻量级开发体验)
  • 命令行编辑器vim + vim-go 插件

验证安装:

运行 go version 检查 Go 是否安装成功。
运行 go env 查看 Go 语言的环境配置。


1.2 Go 语言基本语法

变量和常量

变量声明与赋值

Go 语言支持显式类型声明和类型推导,下面的代码展示了GO中都有哪些声明方式,之后会详细讲解:

var name string = "Go" // 显式声明类型
age := 10              // 类型推导
const pi = 3.14       // 常量声明
  • var 关键字用于显式声明变量类型。
  • := 让 Go 语言自动推导变量类型(仅限于函数内部)。
  • const 定义不可变的常量。

变量作用域和生命周期

  • 局部变量:在函数或代码块内部声明,仅在该作用域内有效。
  • 全局变量:在 package 级别声明,整个包都可以访问。
  • 生命周期:局部变量随函数执行结束而销毁,全局变量存在整个程序运行期间。

示例

package main

import "fmt"

var globalVar = "我是全局变量" // 在整个包范围内有效

func main() {
    
    
    localVar := "我是局部变量" // 仅在 main 函数内有效
    fmt.Println(globalVar)
    fmt.Println(localVar)
}

在这里插入图片描述

var vs := (变量)

var 关键字

var 是 Go 中声明变量的关键字,我们可以使用 var 声明一个或多个变量,并显式地指定变量类型。

1. 声明单个变量

var x int
x = 10

2. 声明多个变量

var x, y int
x = 10
y = 20

3. 声明并初始化变量

var x int = 10

4. 自动推导类型

var x = 10

:= 简短变量声明

:= 是 Go 语言中的简短变量声明形式。它用于函数内部,声明并初始化一个或多个变量。:= 不能用于函数外部(即只能在函数体内使用)。这种声明方式是 Go 语言的特色之一,可以简化代码。

// 单个变量的声明和初始化
x := 10
// 多个变量的声明和初始化
x, y := 10, "hello"
  1. := 会自动根据右侧的值推断类型,不需要显式声明类型。
  2. 在同一个作用域内,变量只能声明一次(即不能重复使用 := 声明同一个变量),如果变量已经声明过,则需要使用 = 来赋值。

常量的定义与使用

Go 语言中的常量使用 const 关键字定义,常量的值在编译时已经确定,不能改变。

常量定义

const Age int = 21 // 显式指定变量类型
const Pi = 3.14
const Greet = "Hello, Go!"

常量组

我们可以使用常量组来定义多个常量,常量组通常用于定义一系列相关的常量。

const (
	x = 10
	y = 20
	z = 30
)

在常量组中,除了第一个常量外,后续常量会自动继承前一个变量的值。
如果我们想为某个常量赋一个新的值,可以显示的指定它。

常量的使用

常量可以像普通变量一样使用,但其值不能在运行时改变:

const maxLimit = 100

func checkLimit(value int) bool {
    
    
	if value > maxLimit {
    
    
		return false;
	}
	return true;
}

常量在 Go 语言中的应用场景包括定义数值限制、状态标识、控制值等。

总结

  • var 是 Go 中声明变量的标准方式,可以显式声明变量类型,也可以不声明类型让 Go 自动推断。
  • := 是 Go 的简短变量声明方式,适用于函数内部,自动推断类型,并同时声明和初始化变量。
  • const 用于定义常量,常量一旦定义就无法改变。常量组和显式类型声明提供了更灵活的方式来组织常量。

1.3 数据类型

Go 语言的数据类型包括基本类型和复合类型。

基本类型

1. 整数类型

Go 语言提供了多种整数类型,包括有符号和无符号整数。

  • int:默认整数类型,大小取决于系统(32 位或 64 位)。
  • int8:8 位有符号整数,范围 -128127
  • int16:16 位有符号整数,范围 -32,76832,767
  • int32:32 位有符号整数,范围 -2,147,483,6482,147,483,647
  • int64:64 位有符号整数,范围 -9,223,372,036,854,775,8089,223,372,036,854,775,807

示例

var a int = 42
var b int8 = 127
var c int16 = -32000
fmt.Println(a, b, c)

在这里插入图片描述

2. 无符号整数类型

无符号整数没有负数,仅用于存储非负整数。

  • uint:默认无符号整数类型,大小取决于系统(32 位或 64 位)。
  • uint8:8 位无符号整数,范围 0255
  • uint16:16 位无符号整数,范围 065,535
  • uint32:32 位无符号整数,范围 04,294,967,295
  • uint64:64 位无符号整数,范围 018,446,744,073,709,551,615

示例

var d uint = 42
var e uint8 = 255
var f uint16 = 60000
fmt.Println(d, e, f)

在这里插入图片描述

3. 浮点数类型

Go 语言支持两种浮点类型:

  • float32:32 位浮点数,精度较低。
  • float64:64 位浮点数,精度较高。

示例

var g float32 = 3.14
var h float64 = 2.1145141919810
fmt.Println(g, h)

在这里插入图片描述

4. 布尔类型

布尔类型 (bool) 只有两个值:truefalse

示例

var i bool = true
var j bool = false
fmt.Println(i, j)

在这里插入图片描述

5. 字符串类型

字符串类型 (string) 用于存储 UTF-8 编码的文本。

示例

var k string = "Hello, Golang"
fmt.Println(k)

在这里插入图片描述

复合类型 与 控制流

【Go语言快速上手】第一部分:数据类型(数组、切片、映射)与控制语句


1.3 面向对象编程

结构体和方法

Go 语言没有传统的类和继承概念,但通过结构体(struct)和方法(method)可以实现面向对象的编程风格。结构体用于组合多个字段,而方法则是绑定到结构体上的函数。

结构体

结构体是 Go 中用于组合数据的复合类型,可以将多个不同类型的字段组合到一起。下面是定义和使用结构体的示例:

// 定义一个结构体 Person
type Person struct {
    
    
	Name string
	Age  int
}

func (p Person) SayHello() {
    
    
	fmt.Println("Hello, my name is", p.Name)
}

func main() {
    
    
	p := Person{
    
    Name: "李田所", Age: 24}
	p.SayHello()
}

在这里插入图片描述

对于上面的示例代码,Person 是一个结构体,包含 NameAge 两个字段。SayHello 是结构体的一个方法,用来打印出结构体中的 Name 字段。

方法接收者

方法接收者是定义方法时,决定该方法属于哪个类型的关键。Go 支持值接收者和指针接收者两种方式。

值接收者

值接收者是指方法接收的是该类型的副本,这意味着方法中修改的只是副本,而不会影响原对象。

// 使用值接收者定义一个方法
func (p Person) GetAge() int {
    
    
    return p.Age
}
指针接收者

指针接收者是指方法接收的是类型的指针,这使得方法可以直接修改原对象的字段值。指针接收者更常用于需要修改接收者的情况。

// 定义结构体 Animal
type Animal struct {
    
    
    Name string
}

// 使用指针接收者来修改 Name 字段
func (a *Animal) SetName(name string) {
    
    
    a.Name = name
}

// 使用指针接收者的方法
func main() {
    
    
    a := Animal{
    
    Name: "Dog"}
    a.SetName("Cat")
    fmt.Println(a.Name)  // 输出 Cat
}

对于上面的示例代码,SetName 使用了指针接收者 *Animal,使得方法可以修改结构体 AnimalName 字段。


1.4 错误处理

error 类型

在 Go 中,错误是通过返回一个 error 类型来处理的。error 是一个内建的接口类型,定义了一个 Error() 方法。通过检查 error 的值,程序可以决定是否需要进一步处理。

以下是一个简单的示例,演示了如何使用 error 类型来处理除法中的除数为零的情况:

// divide 函数执行除法运算,返回一个整数和一个 error
func divide(a, b int) (int, error) {
    
    
    if b == 0 {
    
    
        // 返回自定义错误
        return 0, errors.New("除数不能为0")
    }
    return a / b, nil  // 返回结果和 nil 错误
}

func main() {
    
    
    result, err := divide(10, 0)
    if err != nil {
    
    
        fmt.Println("错误:", err)
    } else {
    
    
        fmt.Println("结果:", result)
    }
}

在这里插入图片描述

对于上面的示例代码,当除数为零时,divide 函数返回一个错误。调用方可以检查返回的 error 值,并作出相应的错误处理。

panicrecover

Go 提供了 panicrecover 来处理运行时错误。panic 用于引发一个程序崩溃的事件,而 recover 用于捕获 panic 引发的崩溃并恢复程序执行。

  • panic 用于发生致命错误时终止程序的执行。
  • recover 用于从 panic 中恢复,并防止程序崩溃。

以下是一个简单的示例,演示了如何使用 panicrecover

// 使用 defer 和 recover 来捕获 panic
// 下面的代码写在函数内部
defer func() {
    
    
    if r := recover(); r != nil {
    
    
        fmt.Println("程序崩溃,恢复成功:", r)
    }
}()

// 发生 panic,程序会崩溃,但会被 recover 恢复
panic("发生错误!")

在这里插入图片描述

对于上面的示例代码,当程序执行到 panic("发生错误!") 时,panic 会引发程序崩溃,但由于在 defer 中使用了 recover,崩溃被捕获并恢复,程序继续执行。


1.5 包管理

go mod 管理依赖

Go 1.11 引入了模块支持,使用 go mod 命令来管理依赖和版本。通过 go mod,可以轻松初始化 Go 项目并管理外部依赖。

  1. 初始化 Go 模块:
go mod init myproject
  1. 安装第三方依赖包:
go get github.com/gin-gonic/gin

go mod 会在项目根目录生成 go.mod 文件,记录项目的依赖信息,便于版本控制和依赖管理。

导入和使用第三方包

一旦依赖被添加到 go.mod 文件中,可以通过 import 语句来导入和使用这些包。例如,使用 github.com/gin-gonic/gin 包来构建一个简单的 Web 应用:

import "github.com/gin-gonic/gin"

func main() {
    
    
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
    
    
        c.JSON(200, gin.H{
    
    
            "message": "Hello, World!",
        })
    })
    r.Run()
}

对于上面的示例代码,gin 包被导入并用来构建一个简单的 HTTP 路由。


猜你喜欢

转载自blog.csdn.net/Dreaming_TI/article/details/145406595
今日推荐