当前位置: 首页 > article >正文

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

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

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

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

目录

一、引言

1、Go语言简介

2、Go语言特点

二、变量

1、变量的声明与初始化

2、变量的作用域 

三、数据类型

1、基本数据类型

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

2. 浮点类型

3. 布尔类型

4. 字符串类型

5. 复数类型

2、复合数据类型

1. 数组(Array)

2. 切片(Slice)

3. 映射(Map)

4. 结构体(Struct)

3、类型转换

1. 整数类型转换

2. 浮点数类型转换

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

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

5. 切片到数组类型转换

6. 数组到切片类型转换

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

8. 结构体类型转换

9. 类型断言


一、引言

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)
}


2. 切片(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)
}


3. 映射(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)
}


4. 结构体(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)
}


2. 浮点数类型转换

将浮点数类型从一种转换为另一种类型,例如从 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)
}


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

将字符串类型转换为整数类型,例如从 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)
}


6. 数组到切片类型转换

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

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)
    }
}


8. 结构体类型转换

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

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)
}


9. 类型断言

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

package main

import (
    "fmt"
)

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

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

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


http://www.kler.cn/news/363836.html

相关文章:

  • 【芯片设计】DC综合retiming策略的学习与实践
  • Android Room(SQLite) too many SQL variables异常
  • nginx的配置
  • 初识知识图谱
  • c语言内核链表
  • 【QT】QChart绘制曲线与散点图
  • perl双引号内字符串的反斜线转义
  • 【Linux系统】Linux系统习题整理
  • zsh: command not found: nvm 问题(Mac)
  • 得物iOS函数调用栈及符号化调优实践|得物技术
  • 【前端布局 如何适配不同分辨率 vue2】
  • 12、论文阅读:利用生成对抗网络实现无监督深度图像增强
  • 【Java】多线程-线程创建的两种方式【主线学习笔记】
  • 在vue中key的原理是什么,有什么作用
  • 《Vue.js 组件开发秘籍:从基础到高级》
  • CTFHUB技能树之文件上传——无验证
  • sql-labs靶场第十六关测试报告
  • 一款精美的导航引导页html源码
  • STM32 从0开始系统学习 1
  • 从0开始深度学习(20)——延后初始化和自定义层
  • Text实现美团部分样式
  • 代码随想录刷题学习日记
  • 基础知识 main函数形参 C语言
  • C++:模板的特化与分离编译
  • Python re 模块:正则表达式的强大工具
  • 全局滚动和局部滚动