0


【Go语言】语法基础之变量、数据类型详解

🐇明明跟你说过:个人主页

🏅个人专栏:《Go语言探索之旅》🏅

🔖行路有良友,便是天堂🔖

一、引言

1、Go语言简介

Go语言,又称Golang,是由Google公司开发的一种现代编程语言。它起源于2007年,并在2009年正式对外发布。Go语言旨在提高软件开发的效率、可靠性和可维护性,特别在处理并发性方面表现出色。

2、Go语言特点

  1. 并发性支持:Go语言内置并发性支持,允许开发者构建高度并发和可扩展的应用。它提供了goroutine(轻量级线程)和channel(通信管道)等功能,简化了并发编程。
  2. 垃圾回收:Go语言拥有高效的垃圾回收机制,自动释放不再使用的内存。这减轻了开发者管理内存的负担,提高了程序的稳定性和可靠性。
  3. 类型安全:Go语言是一种强类型语言,提供了严格的类型检查机制。这有助于捕获类型错误,确保代码的可靠性。
  4. 跨平台性:Go语言编译成可执行文件后,可以在不同的操作系统(如Linux、Windows、macOS)上运行,无需进行重新编译。
  5. 高性能:Go语言编译器生成高度优化的机器代码,使程序运行速度快且资源消耗低。它特别适合处理高并发和数据密集型应用。

二、变量

1、变量的声明与初始化

1. 使用 var 关键字声明变量
使用 var 关键字声明变量是最基本的形式。可以声明一个或多个变量,并分别初始化它们:

var (
    x int         // 声明一个 int 类型的变量 x
    y string      // 声明一个 string 类型的变量 y
    z float64     // 声明一个 float64 类型的变量 z
)

// 初始化变量
x = 10
y = "hello"
z = 3.14

2. 使用 := 简化声明和初始化
如果想要在声明的同时初始化变量,可以使用 := 运算符,这种方式被称为“简短变量声明”。这种方式只在函数内部有效:

a := 10        // 声明并初始化一个 int 类型的变量 a
b := "world"   // 声明并初始化一个 string 类型的变量 b
c := 2.718     // 声明并初始化一个 float64 类型的变量 c

3. 同时声明多个变量
可以在一行中声明并初始化多个变量:

var (
    d int    = 100 // 声明并初始化一个 int 类型的变量 d
    e string = "Go" // 声明并初始化一个 string 类型的变量 e
    f float64 = 1.618 // 声明并初始化一个 float64 类型的变量 f
)

或者使用简短声明:

g, h, i := 1000, "Programming", 3.14159

4. 使用 new 函数
new 函数可以用来为变量分配内存,并返回指向该内存的指针:

j := new(int) // 分配 int 类型的内存,并返回指向该内存的指针
*k := 1000    // 给指针 k 所指向的 int 类型内存赋值

5. 使用 make 函数
对于某些类型(如切片、映射和通道),需要使用 make 函数来初始化:

slice := make([]int, 5) // 创建一个长度为 5 的 int 类型切片
mapVar := make(map[string]int) // 创建一个 string 到 int 的映射
channel := make(chan int) // 创建一个 int 类型的通道

6. 匿名变量
在某些情况下,可能会使用匿名变量(通常写作 _),主要用于忽略不需要的返回值:

_, err := os.Open("file.txt") // 忽略第一个返回值
if err != nil {
    log.Fatal(err)
}

7. 初始化复合类型
可以一次性初始化数组、切片、映射等复合类型:

// 数组
arr := [3]int{1, 2, 3}

// 切片
slice := []int{1, 2, 3}

// 映射
mapVar := map[string]int{"one": 1, "two": 2, "three": 3}

2、变量的作用域

在 Go 语言中,变量的作用域决定了变量的可见性和生命周期。作用域的定义有助于避免命名冲突,并确保变量在适当的时候被创建和销毁。Go 语言中的变量作用域主要有以下几种:

1. 包级变量(Package-Level Variables)
包级变量在整个包内可见,并且在整个程序运行期间存在。这类变量通常用于在包内共享状态。

package main

var globalVar int // 包级变量

func main() {
    globalVar = 10
    fmt.Println(globalVar)
}

2. 函数级变量(Function-Level Variables)
函数级变量在一个函数的范围内可见,并且在函数被调用时创建,在函数返回时销毁。

package main

import "fmt"

func main() {
    funcLevelVar := 10 // 函数级变量
    fmt.Println(funcLevelVar)
}

3. 块级变量(Block-Level Variables)
块级变量在一个代码块(由 {} 围绕的部分)内可见,并且在进入该代码块时创建,在离开该代码块时销毁。

package main

import "fmt"

func main() {
    if true {
        blockLevelVar := 10 // 块级变量
        fmt.Println(blockLevelVar)
    }
    // blockLevelVar 不可见
}

4. 形参(Function Parameters)
函数的形参在函数调用时创建,并在函数返回时销毁。形参的作用域限于函数体内。

package main

import "fmt"

func printSum(a, b int) { // 形参 a 和 b
    sum := a + b
    fmt.Println(sum)
}

func main() {
    printSum(3, 4)
}

5. 循环变量
在循环中声明的变量在循环体内可见,并且在每次迭代时创建,在迭代结束后销毁。

package main

import "fmt"

func main() {
    for i := 0; i < 5; i++ { // 循环变量 i
        fmt.Println(i)
    }
    // i 在循环外部不可见
}

6. 闭包中的外部变量
在闭包中,闭包可以访问定义在其外围作用域中的变量。这些变量的作用域扩展到了闭包的生命周期内。

package main

import "fmt"

func main() {
    x := 10 // 外围作用域中的变量

    f := func() {
        fmt.Println(x)
    }

    f() // 输出 x 的值
}

7. 匿名变量
匿名变量(通常写作 _)用于忽略不需要的返回值或变量。

package main

import (
    "fmt"
    "os"
)

func main() {
    _, err := os.Open("file.txt")
    if err != nil {
        fmt.Println("Error opening file:", err)
    }
}

三、数据类型

1、基本数据类型

1. 整数类型(int,uint,byte等)

整数类型用于表示整数值,包括有符号整数和无符号整数。

有符号整数类型

  • int:默认的整数类型,其大小取决于操作系统(32位或64位)。
  • int8:8位有符号整数,范围为 -128 到 127。
  • int16:16位有符号整数,范围为 -32768 到 32767。
  • int32:32位有符号整数,范围为 -2^31 到 2^31-1。
  • int64:64位有符号整数,范围为 -2^63 到 2^63-1。

无符号整数类型

  • uint:默认的无符号整数类型,其大小取决于操作系统(32位或64位)。
  • uint8:8位无符号整数,范围为 0 到 255。
  • byte:别名类型,等同于 uint8。
  • uint16:16位无符号整数,范围为 0 到 65535。
  • uint32:32位无符号整数,范围为 0 到 2^32-1。
  • uint64:64位无符号整数,范围为 0 到 2^64-1。
  • uintptr:用于存储指针地址的整数类型,其大小取决于操作系统(32位或64位)。

2. 浮点类型

浮点类型用于表示带有小数部分的数字。

  • float32:32位浮点数,约7位精度。
  • float64:64位浮点数,约15位精度。

3. 布尔类型

布尔类型用于表示真或假的值。

  • bool:布尔值,可以是 true 或 false。

4. 字符串类型

字符串类型用于表示文本。

  • string:用于表示文本的字符串类型。

5. 复数类型

复数类型用于表示具有实部和虚部的数值。

  • complex64:包含实部和虚部的32位复数。
  • complex128:包含实部和虚部的64位复数。

示例代码

package main

import (
    "fmt"
)

func main() {
    // 整数类型
    var intVar int = 42
    var int8Var int8 = -128
    var int16Var int16 = 32767
    var int32Var int32 = 2147483647
    var int64Var int64 = 9223372036854775807
    var uintVar uint = 42
    var uint8Var uint8 = 255
    var uint16Var uint16 = 65535
    var uint32Var uint32 = 4294967295
    var uint64Var uint64 = 18446744073709551615
    var byteVar byte = 'A' // 等同于 uint8
    var uintptrVar uintptr = 12345

    // 浮点类型
    var float32Var float32 = 3.14
    var float64Var float64 = 3.1415926535

    // 布尔类型
    var boolVar bool = true

    // 字符串类型
    var stringVar string = "Hello, World!"

    // 复数类型
    var complex64Var complex64 = 3 + 4i
    var complex128Var complex128 = 3 + 4i

    // 输出变量的值
    fmt.Printf("intVar = %d\n", intVar)
    fmt.Printf("int8Var = %d\n", int8Var)
    fmt.Printf("int16Var = %d\n", int16Var)
    fmt.Printf("int32Var = %d\n", int32Var)
    fmt.Printf("int64Var = %d\n", int64Var)
    fmt.Printf("uintVar = %d\n", uintVar)
    fmt.Printf("uint8Var = %d\n", uint8Var)
    fmt.Printf("uint16Var = %d\n", uint16Var)
    fmt.Printf("uint32Var = %d\n", uint32Var)
    fmt.Printf("uint64Var = %d\n", uint64Var)
    fmt.Printf("byteVar = %c\n", byteVar)
    fmt.Printf("uintptrVar = %d\n", uintptrVar)
    fmt.Printf("float32Var = %f\n", float32Var)
    fmt.Printf("float64Var = %f\n", float64Var)
    fmt.Printf("boolVar = %t\n", boolVar)
    fmt.Printf("stringVar = %s\n", stringVar)
    fmt.Printf("complex64Var = %v\n", complex64Var)
    fmt.Printf("complex128Var = %v\n", complex128Var)
}

2、复合数据类型

Go 语言提供了多种复合数据类型来处理更复杂的数据结构。以下是一些常见的复合数据类型及其描述:

1. 数组(Array)

数组是一种固定大小的序列类型,用于存储相同类型的元素。数组的长度在声明时确定,并且不可改变。

package main

import "fmt"

func main() {
    // 声明并初始化数组
    var numbers [5]int = [5]int{1, 2, 3, 4, 5}
    
    // 访问数组元素
    fmt.Println("numbers[0] =", numbers[0])
    fmt.Println("numbers[4] =", numbers[4])

    // 遍历数组
    for i := range numbers {
        fmt.Println("numbers[", i, "] =", numbers[i])
    }

    // 声明并初始化不同类型的数组
    var letters = [5]string{"a", "b", "c", "d", "e"}
    var floats = [5]float64{1.1, 2.2, 3.3, 4.4, 5.5}
    
    // 打印数组
    fmt.Println("letters =", letters)
    fmt.Println("floats =", floats)
}

  1. 切片(Slice)

切片是基于数组的一种动态数据结构,它可以动态地增长和缩减。切片提供了一种灵活的方式来管理序列数据。

package main

import "fmt"

func main() {
    // 声明并初始化切片
    var numbers = []int{1, 2, 3, 4, 5}

    // 访问切片元素
    fmt.Println("numbers[0] =", numbers[0])
    fmt.Println("numbers[4] =", numbers[4])

    // 遍历切片
    for i, v := range numbers {
        fmt.Println("numbers[", i, "] =", v)
    }

    // 修改切片
    numbers[0] = 10
    fmt.Println("Modified numbers =", numbers)

    // 切片的追加
    numbers = append(numbers, 6)
    fmt.Println("Appended numbers =", numbers)

    // 切片的切分
    subSlice := numbers[1:4]
    fmt.Println("Subslice =", subSlice)
}

  1. 映射(Map)

映射是一种关联类型,它通过键值对来存储数据。键必须是可比较的类型(如 int、string、struct 等),值可以是任意类型。

package main

import "fmt"

func main() {
    // 声明并初始化映射
    var ageMap = map[string]int{
        "Alice": 30,
        "Bob":   25,
        "Charlie": 22,
    }

    // 访问映射元素
    fmt.Println("ageMap[Alice] =", ageMap["Alice"])
    fmt.Println("ageMap[Bob] =", ageMap["Bob"])

    // 遍历映射
    for key, value := range ageMap {
        fmt.Println("key =", key, "value =", value)
    }

    // 修改映射
    ageMap["Alice"] = 31
    fmt.Println("Updated ageMap =", ageMap)

    // 添加新的键值对
    ageMap["David"] = 28
    fmt.Println("Updated ageMap =", ageMap)

    // 删除映射中的键值对
    delete(ageMap, "Charlie")
    fmt.Println("Updated ageMap =", ageMap)
}

  1. 结构体(Struct)

结构体是一种自定义的数据类型,它允许你组合不同的数据类型来形成新的类型。

package main

import "fmt"

type Person struct {
    Name string
    Age  int
    Address Address
}

type Address struct {
    Street string
    City   string
}

func main() {
    // 声明并初始化结构体
    var person = Person{
        Name: "Alice",
        Age:  30,
        Address: Address{
            Street: "123 Main St",
            City:   "Anytown",
        },
    }

    // 访问结构体成员
    fmt.Println("person.Name =", person.Name)
    fmt.Println("person.Age =", person.Age)
    fmt.Println("person.Address.Street =", person.Address.Street)
    fmt.Println("person.Address.City =", person.Address.City)
}

3、类型转换

在 Go 语言中,类型转换是指将一个变量或表达式的类型转换为另一种类型。类型转换在某些情况下是必要的,尤其是在需要将一种类型的数据作为另一种类型来处理时。

基本类型转换

1. 整数类型转换

将整数类型从一种转换为另一种类型,例如从 int 转换为 int32。

import "fmt"

func main() {
    var i int = 10
    var i32 int32 = int32(i) // 类型转换
    fmt.Printf("Original integer: %d, Converted integer: %d\n", i, i32)
}

  1. 浮点数类型转换

将浮点数类型从一种转换为另一种类型,例如从 float32 转换为 float64。

package main

import "fmt"

func main() {
    var f32 float32 = 3.14
    var f64 float64 = float64(f32) // 类型转换
    fmt.Printf("Original float32: %f, Converted float64: %f\n", f32, f64)
}

  1. 字符串到整数类型转换

将字符串类型转换为整数类型,例如从 string 转换为 int。

package main

import (
    "fmt"
    "strconv"
)

func main() {
    s := "123"
    i, err := strconv.Atoi(s) // 字符串转整数
    if err == nil {
        fmt.Printf("Converted integer: %d\n", i)
    } else {
        fmt.Println("Conversion error:", err)
    }
}

4. 整数到字符串类型转换

将整数类型转换为字符串类型,例如从 int 转换为 string。

package main

import (
    "fmt"
    "strconv"
)

func main() {
    i := 123
    s := strconv.Itoa(i) // 整数转字符串
    fmt.Printf("Converted string: %s\n", s)
}

复合类型转换

5. 切片到数组类型转换

将切片转换为数组,需要注意的是,切片和数组的长度必须相等。

package main

import "fmt"

func main() {
    s := []int{1, 2, 3}
    var a [3]int
    copy(a[:], s) // 切片转数组
    fmt.Printf("Converted array: %v\n", a)
}

  1. 数组到切片类型转换

将数组转换为切片,可以通过切片操作来实现。

package main

import "fmt"

func main() {
    a := [3]int{1, 2, 3}
    s := a[:] // 数组转切片
    fmt.Printf("Converted slice: %v\n", s)
}

7. 映射(Map)相关的类型转换

在映射中,键和值的类型转换通常在插入或检索时进行。

package main

import "fmt"

func main() {
    m := map[string]int{
        "one":   1,
        "two":   2,
        "three": 3,
    }
    val, ok := m["one"]
    if ok {
        strVal := strconv.Itoa(val) // 将整数转换为字符串
        fmt.Printf("Converted value: %s\n", strVal)
    }
}

  1. 结构体类型转换

在某些情况下,可能需要将结构体转换为另一种类型,例如将一个结构体嵌入另一个结构体。

package main

import "fmt"

type Point struct {
    X int
    Y int
}

type Circle struct {
    Point
    Radius int
}

func main() {
    p := Point{X: 10, Y: 20}
    c := Circle{Point: p, Radius: 5} // 结构体嵌入
    fmt.Printf("Circle: %+v\n", c)
}

  1. 类型断言

类型断言用于从接口(interface)中提取具体的类型值。

package main

import (
    "fmt"
)

func main() {
    var i interface{} = "hello"
    if str, ok := i.(string); ok {
        fmt.Println("String value:", str)
    }
}

💕💕💕每一次的分享都是一次成长的旅程,感谢您的陪伴和关注。希望这些关于Go语言的文章能陪伴您走过技术的一段旅程,共同见证成长和进步!😺😺😺

🧨🧨🧨让我们一起在技术的海洋中探索前行,共同书写美好的未来!!!

标签: go go1.19 后端

本文转载自: https://blog.csdn.net/weixin_53269650/article/details/143145273
版权归原作者 明明跟你说过 所有, 如有侵权,请联系我们删除。

“【Go语言】语法基础之变量、数据类型详解”的评论:

还没有评论