Go 语言基础学习文档

Go 语言基础学习文档

一、环境搭建

1.1 下载与安装

1.2 安装验证

  1. 验证有没有安装成功

    cmd 复制代码
    go version

    打印输出类似"go version go1.24.2 windows/amd64",说明安装成功。

  2. 查看 Go 环境

    cmd 复制代码
    go env

    Go1.11 版本之后无需手动配置环境变量,使用 go mod 管理项目,也不需要非得把项目放到 GOPATH 目录下,你可以在任意位置新建项目。

    Go1.13 以后可以彻底不要 GOPATH 了。

1.3 开发工具

  1. 推荐使用 VSCode
  2. VSCode 安装 Go 语言插件(插件名称:Go)

二、基础语法

2.1 fmt 模块(格式化输出)

2.1.1 Print

用于基本打印输出,多参数打印无空格。

go 复制代码
fmt.Print("a")
// a

fmt.Print("a", "b", "c")
// abc (PS:打印多个时,不会有空格)
2.1.2 Println

用于打印输出并支持格式化。

go 复制代码
fmt.Println("a")
// a
// 换行

fmt.Println("a", "b", "c")
// a b c (PS:打印多个时,会有空格)
// 换行
2.1.3 Printf

用于格式化打印输出,支持占位符。

go 复制代码
var a = 1
var b = 2
var c = 3

fmt.Printf("a=%v,b=%v,c=%v", a, b, c)
// a=1,b=2,c=3

fmt.Printf("a=%v,a的类型是%T", a, a)
// a=1,a的类型是int

2.2 变量与常量

2.2.1 变量

变量是程序运行过程中可以改变的量,Go 语言支持两种声明方式。

  1. var 变量声明法

    • 适用范围:可用于全局变量和局部变量。

    • 基本用法

      go 复制代码
      // 声明变量
      var a string
      // 变量赋值
      a = "a"
      
      // 声明变量并赋值
      var a string = "a"
      // 声明变量并赋值,简写(类型推导,可省略)
      vat a = "a"
      
      // 一次声明多个变量(多个变量的类型都一样)
      var a, b, c, string
      a = "a"
      b = "b"
      c = "c"
      
      // 一次声明多个变量,(多个变量的类型可以不一样)
      var (
      	a string
      	b int
      	c bool
      )
      
      // 一次声明多个变量并赋值
      var (
      	a string = "a"
      	b int    = 1
      	c bool   = true
      )
      
      // 一次声明多个变量并赋值,简写(类型推导,可省略)
      var (
      	a = "a"
      	b = 1
      	c = true
      )
  2. 短变量声明法

    • 适用范围:仅用于函数内部的局部变量。

    • 基本用法

      go 复制代码
      // 声明变量并赋值
      a := "a"
      
      // 一次声明多个变量并赋值
      a, b, c := "a", 1, true
2.2.2 常量

常量是恒定不变的值,定义时必须赋值。

  1. const 定义常量

    go 复制代码
    // 声明常量并赋值
    const a = "a"
    
    // 一次性声明多个常量并赋值
    const (
    	a = "a"
        b = "b"
    )
  2. 常量省略值的特性

    同时声明多个常量时,若省略值,则表示和上一行的值相同。

    go 复制代码
    const (
    	a = "a"
    	b
    	c
    )
    fmt.Printf("a = %v, b = %v, c = %v\n", a, b, c)
    // a = a, b = a, c = a

2.3 数据类型

Go 语言数据类型分为 基本数据类型复合数据类型 两大类。

  • 基本数据类型:整型、浮点型、布尔型、字符串
  • 复合数据类型:数组、切片、结构体、函数、map、通道(channel)、接口等
2.3.1 整型 int

整型分为 有符号整型无符号整型 两类,不同类型占用字节数不同。

  1. 声明示例

    go 复制代码
    var num int = 1
    fmt.Printf("num=%v,类型=%T\n", num, num)
    // num=1,类型=int
  2. 整型分类

    类型 有无符号 位数 取值范围 备注
    int8 有符号 8 -128 到 127(-2^7到2^7-1)
    int16 有符号 16 -32768 到 32767(-2^15到2^15-1)
    int32 有符号 32 -2147483648 到 2147483647(-2^31到2^31-1) 别名:rune
    int64 有符号 64 -9223372036854775808 到 9223372036854775807(-2^63到2^63-1)
    uint8 无符号 8 0 到 255(0到2^8-1) 别名:byte
    uint16 无符号 16 0 到 65535(0到2^16-1)
    uint32 无符号 32 0 到 4294967295(0到2^32-1)
    uint64 无符号 64 0 到 18446744073709551615(0到2^64-1)
    int 有符号 系统相关 32位系统同int32,64位系统同int64 推荐优先使用
    uint 无符号 系统相关 32位系统同uint32,64位系统同uint64
    uintptr 无符号 系统相关 足够存储指针值的无符号整数 用于底层编程(如指针操作)
  3. 整型类型转换

    不同整型之间无法直接运算,需要强制类型转换,高位转低位时需注意数据溢出。

    go 复制代码
    // 不同类型直接运算报错
    var num1 int8 = 1
    var num2 int16 = 1
    fmt.Println(num1 + num2) // 报错
    
    // 强制类型转换后运算
    var num1 int8 = 1
    var num2 int16 = 1
    fmt.Println(int16(num1) + num2) // 输出:2
    
    // 高位转低位的溢出问题
    var num1 int16 = 130
    fmt.Println(int8(num1)) // 输出:-126
  4. 数字字面量格式

    符号 描述
    %d 表示十进制输出
    %b 表示二进制输出
    %o 表示八进制输出
    %x 表示十六进制输出

    示例代码

    go 复制代码
    num := 16
    fmt.Printf("num=%v\n", num)  // 输出:num=16
    fmt.Printf("num=%d\n", num)  // 输出:num=16
    fmt.Printf("num=%b\n", num)  // 输出:num=10000
    fmt.Printf("num=%o\n", num)  // 输出:num=20
    fmt.Printf("num=%x\n", num)  // 输出:num=10
  5. 获取变量占用字节数

    使用 unsafe.Sizeof 函数可以返回变量占用的字节数。

    go 复制代码
    num1 := int(1)
    num2 := int8(1)
    num3 := int16(1)
    num4 := int32(1)
    num5 := int64(1)
    
    fmt.Println(unsafe.Sizeof(num1)) // 输出:8
    fmt.Println(unsafe.Sizeof(num2)) // 输出:1
    fmt.Println(unsafe.Sizeof(num3)) // 输出:2
    fmt.Println(unsafe.Sizeof(num4)) // 输出:4
    fmt.Println(unsafe.Sizeof(num5)) // 输出:8
2.3.2 浮点型 float

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

  1. 声明示例

    go 复制代码
    // 类型推导,默认是float64
    num := 3.1415926
    fmt.Printf("num=%v,类型=%T\n", num, num) // 输出:num=3.1415926,类型=float64
    
    // 显式声明float32
    num1 := float32(3.1415926)
    fmt.Printf("num1=%v,类型=%T\n", num1, num1) // 输出:num1=3.1415925,类型=float32
    
    // 显式声明float64
    num2 := float64(3.1415926)
    fmt.Printf("num2=%v,类型=%T\n", num2, num2) // 输出:num2=3.1415926,类型=float64
  2. 浮点型范围

    • float32:最大范围约为 3.4e38

    • float64:最大范围约为 1.8e308

      示例代码

      go 复制代码
      fmt.Println(math.MaxFloat32) // 输出:3.4028234663852886e+38
      fmt.Println(math.MaxFloat64) // 输出:1.7976931348623157e+308
  3. 格式化输出

    使用 %f 占位符输出浮点型,可指定小数位数。

    go 复制代码
    num1 := 3.1415926
    fmt.Printf("%v\n", num1)    // 输出:3.1415926
    fmt.Printf("%f\n", num1)    // 输出:3.141593(默认保留6位,四舍五入)
    fmt.Printf("%.2f\n", num1)  // 输出:3.14(保留2位)
    fmt.Printf("%.3f\n", num1)  // 输出:3.142(保留3位)
  4. 科学计数法

    浮点型支持科学计数法表示。

    go 复制代码
    num1 := 3.14e2
    fmt.Printf("num1=%v,类型=%T\n", num1, num1) // 输出:num1=314,类型=float64
    
    num2 := 3.14e-2
    fmt.Printf("num2=%v,类型=%T\n", num2, num2) // 输出:num2=0.0314,类型=float64
  5. 精度丢失问题

    二进制浮点数转换为十进制时可能存在精度丢失,可使用第三方包 github.com/shopspring/decimal 解决。

    go 复制代码
    num := 1129.6
    fmt.Println(num * 100) // 输出:112959.99999999999
    
    num1 := 8.2
    num2 := 3.8
    fmt.Println(num1 - num2) // 输出:4.3999999999999995
  6. 浮点型与整型转换

    • 整型转浮点型:直接强制转换,不会丢失数据

      go 复制代码
      num1 := 3
      num2 := float32(num1)
      fmt.Printf("num2=%v,类型=%T\n", num2, num2) // 输出:num2=3,类型=float32
      
      num3 := float64(num1)
      fmt.Printf("num3=%v,类型=%T\n", num3, num3) // 输出:num3=3,类型=float64
    • 浮点型转整型:强制转换会丢失小数部分

      go 复制代码
      num1 := 3.14
      num2 := int(num1)
      fmt.Printf("num2=%v,类型=%T\n", num2, num2) // 输出:num2=3,类型=int
2.3.2 布尔类型 bool

布尔型用 bool 表示,只有 truefalse 两个值。

  1. 注意事项

    • 布尔型变量默认值为 false
    • 不允许将整型强制转换为布尔型
    • 布尔型无法参与数值运算,也无法与其他类型转换
  2. 示例代码

    go 复制代码
    var flag bool
    fmt.Printf("布尔类型的默认值=%v,类型=%T\n", flag, flag) // 输出:布尔类型的默认值=false,类型=bool
    
    num := 1
    flag = bool(num) // 报错
    if num { // 报错
        fmt.Println("num为真")
    }
    
    str := "hello"
    flag = bool(str) // 报错
    if str { // 报错
        fmt.Println("str为真")
    }
2.3.4 字符串

字符串的值用双引号 "" 或反引号 ``` ````` 包裹。

  1. 注意事项

    • 双引号用于表示单行字符串,支持转义符。
    • 反引号用于表示多行字符串,原样输出内容,不解析转义符。
    • 单引号 '' 用于表示字符,而非字符串。
  2. 字符串转义符

    常见转义符如下表:

    转义符 含义
    \r 回车符
    \n 换行符
    \t 制表符
    \' 单引号
    \" 双引号
    \\ 反斜杠

    示例代码

    go 复制代码
    str := "mumu: \"hello golang\""
    fmt.Println(str) // 输出:mumu: "hello golang"
  3. 多行字符串

    Go 语言中要定义一个多行字符串时,就必须使用反引号。

    go 复制代码
    multiLine := `这是第一行
    这是第二行
    	这是带缩进的第三行
    这是第四行`
    	fmt.Println(multiLine)
    // 这是第一行
    // 这是第二行
    //         这是带缩进的第三行
    // 这是第四行
  4. 字符串常用的方法

    方法 功能 示例
    len(str) 返回字符串字节数 str := "mumu"; fmt.Println(len(str)) // 输出:4
    + 拼接字符串 fmt.Println("hello" + " golang") // 输出:hello golang
    fmt.Sprintf 格式化拼接字符串 str1:="hello";str2:="golang";str3:=fmt.Sprintf("%v %v",str1,str2) // str3为hello golang
    strings.Split(str, sep) 按分隔符分割字符串,返回切片 str:="hello golang";arr:=strings.Split(str," ");fmt.Println(arr) // 输出:[hello golang]
    strings.Join(arr, sep) 将切片按分隔符合并为字符串 arr:=[]string{"hello","golang"};str:=strings.Join(arr,"-");fmt.Println(str) // 输出:hello-golang
    strings.Contains(str1, str2) 判断 str1 是否包含 str2 str1:="hello golang";str2:="ello";fmt.Println(strings.Contains(str1,str2)) // 输出:true
    strings.HasPrefix(str1, str2) 判断 str1 是否以 str2 开头 str1:="hello golang";str2:="hello";fmt.Println(strings.HasPrefix(str1,str2)) // 输出:true
    strings.HasSuffix(str1, str2) 判断 str1 是否以 str2 结尾 str1:="hello golang";str2:="golang";fmt.Println(strings.HasSuffix(str1,str2)) // 输出:true
    strings.Index(str, substr) 查找 substr 在 str 中首次出现的索引,不存在返回 -1 fmt.Println(strings.Index("hello golang","golang")) // 输出:6
    strings.LastIndex(str, substr) 查找 substr 在 str 中最后出现的索引,不存在返回 -1 fmt.Println(strings.LastIndex("hello golang","an")) // 输出:9
2.3.5 byte & rune

byterune 是 Go 语言中用于表示字符的专属类型,底层都是整型的别名。

  1. byte 与 rune 的区别

    类型 底层类型 占用字节 适用场景
    byte uint8 1 表示 ASCII 字符(0-127 范围)
    rune int32 4 表示 Unicode 字符(如中文、emoji 等)
  2. 字符串遍历

    • for i 循环遍历(按字节)

      Go 字符串底层是字节数组,for i 循环遍历的是每个字节的值。

      go 复制代码
      s := "Hello 世界"
      for i := 0; i < len(s); i++ {
          fmt.Printf("%x ", s[i]) // 输出:48 65 6c 6c 6f 20 e4 b8 96 e7 95 8c
      }
    • for range 遍历(按 rune)

      for range 会自动将字符串按 Unicode 字符拆分,遍历的是 rune 类型的值。

      go 复制代码
      s := "Hello 世界"
      for _, r := range s {
          fmt.Printf("%c ", r) // 输出:H e l l o  世 界
      }
  3. 字符串长度计算

    • len (str):返回字节数

      对于包含多字节字符的字符串,字节数大于字符数。

      go 复制代码
      str:= "go 你好"
      fmt.Println(len(str)) // 输出:9(go占2字节,空格占1,你好各占3,共2+1+3+3=9)
    • len ([] rune (str)):返回字符数

      将字符串转为 rune 切片后,再计算长度即可得到字符数。

      go 复制代码
      str:= "go 你好"
      fmt.Println(len([]rune(str))) // 输出:5
    • utf8.RuneCountInString (str):返回字符数

      使用 unicode/utf8 包的函数直接获取字符数。

      go 复制代码
      str:= "go 你好"
      fmt.Println(utf8.RuneCountInString(str)) // 输出:5

持续更新中...

相关推荐
研究司马懿9 小时前
【云原生】Gateway API高级功能
云原生·go·gateway·k8s·gateway api
梦想很大很大1 天前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰1 天前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘1 天前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤1 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt112 天前
AI DDD重构实践
go
Grassto3 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto5 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室6 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题6 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo