Post

Day02(入门基础)

数据类型

整型

有符号整型(Signed Integer)和无符号整型(Unsigned Integer)是计算机编程中两种基本的整型数据类型,它们的主要区别在于如何解释存储在计算机中的二进制数值

  • 有符号整型(Signed Integer)

    • 表示范围:有符号整型可以表示正数、负数和零。因为它们需要表示正负,所以它们的取值范围是关于零对称的。例如,一个 8 位的有符号整型(int8),可以表示-128 到 127 之间的整数。
    • 表示方法:在计算机内部,有符号整型的最高位(也称为符号位)用于表示数的正负。通常,如果符号位为 0,表示该数为正;如果符号位为 1,表示该数为负。剩下的位用于表示数值的大小。有符号整数的表示方法通常有两种:原码、反码和补码,其中补码是最常用的表示方法。
    • 应用场景:当需要处理的数据可能为正数、负数或零时,应使用有符号整型。
  • 无符号整型(Unsigned Integer)

    • 表示范围:无符号整型只能表示正数和零,不能表示负数。因此,它们的取值范围是从 0 到某个最大值。例如,一个 8 位的无符号整型(uint8),可以表示 0 到 255 之间的整数。
    • 表示方法:无符号整型的所有位都用于表示数值的大小,没有专门的符号位。因此,对于相同位数的整型,无符号整型能够表示的数值范围是有符号整型的两倍(仅考虑正数部分)。
    • 应用场景:当处理的数据只可能为正数或零时,如表示像素值、颜色分量、数量、大小等,应使用无符号整型。此外,在网络通信和硬件编程中,无符号整型也经常被用来表示数据的大小、地址偏移等。

      类型名称 位大小 最小值 最大值
      int8 8 位 -128 127
      int16 16 位 -32,768 32,767
      int32(或 rune 32 位 -2,147,483,648 2,147,483,647
      int64 64 位 -9,223,372,036,854,775,808 9,223,372,036,854,775,807
      uint8(或 byte 8 位 0 255
      uint16 16 位 0 65,535
      uint32 32 位 0 4,294,967,295
      uint64 64 位 0 18,446,744,073,709,551,615

浮点型

浮点型分为float32float64两种,分别表示 32 位和 64 位的浮点数值。以下是这两种浮点型的范围,以表格形式呈现:

类型名称 位大小 最小值 最大值
float32 32 位 约等于 -3.4028235e+38 约等于 3.4028235e+38
float64 64 位 约等于 -1.7976931348623157e+308 约等于 1.7976931348623157e+308

通常推荐使用float64类型,因为它提供了更高的精度和更大的取值范围。然而,在需要节省内存空间或对性能有严格要求的场景下,可以考虑使用float32类型

布尔型

布尔型使用 bool 类型表示,布尔型只有两个取值

  • true
  • false(默认)

字符串类型

在 Go 语言中,字符串类型(string)是一种内置的数据类型,用于表示文本数据。字符串是由零个或多个字符组成的序列,这些字符可以是字母、数字、标点符号、特殊字符等。

  • 字符串在 Go 语言中的表示方式是用双引号("")或反引号(``)括起来的一系列字符。例如

    1
    2
    
    s1 := "Hello, World!"
    s2 := `This is a raw string literal.`
    
  • 在 Go 语言中,字符串是不可变的(immutable),即一旦创建了一个字符串,就不能再修改它的内容。如果需要修改字符串,通常需要创建一个新的字符串。

  • 字符串在 Go 语言中的功能特点包括:

    1. 数据存储与序列化:字符串类型常用于数据的存储和序列化。例如,可以将数据转换为 JSON 格式的字符串进行存储和传输,或者将字符串解析为数据结构进行反序列化。
    2. 网络通信与数据交互:在网络通信和数据交互中,字符串类型用于表示和传输各种信息。例如,HTTP 请求和响应中的数据通常以字符串的形式进行传输,API 接口也常使用字符串表示参数和返回值。
    3. 文件读写与日志记录:字符串类型用于文件读写和日志记录,例如读取文本文件的内容、写入日志信息等。在文件读写和日志记录过程中,字符串类型能够有效地处理和操作文本数据。
  • 字符串在 Go 语言中的内部表示通常是一个字符数组(byte slice)的引用,其中每个字符可能是一个字节(对于 ASCII 字符)或多个字节(对于 UTF-8 编码的多字节字符)。在 Go 语言中,字符串类型提供了许多内置的方法来操作和处理字符串,例如连接、拆分、查找、替换等。

  • 此外,Go 语言还提供了两种特殊的字符类型来处理字符串中的字符:

    • byte 类型(等价于 uint8):用于表示 ASCII 字符集中的字符,每个字符占用一个字节。
    • rune 类型(等价于 int32):用于表示 Unicode 字符集中的字符,可以表示包括中文、日文等任何 Unicode 字符。在处理包含多字节字符的字符串时,通常使用 rune 类型来遍历和访问字符串中的每个字符。

其他

在 Go 语言中,除了整型(integer types)、浮点型(floating-point types)、布尔型(bool)和字符串类型(string)之外,还有其他几种基本数据类型。以下是 Go 语言中的一些主要数据类型:

复合类型

  • 数组(Array):一种具有固定长度的序列,其中每个元素都是相同的数据类型。
  • 切片(Slice):一种动态大小的、灵活的、可变的序列,底层是数组的引用。
  • 映射(Map):一种无序的键值对集合,其中键是唯一的,并且可以是任何可比较的类型(如整数、字符串等)。
  • 通道(Channel):一种类型安全的、阻塞的、先进先出的数据结构,用于在 Go 语言的 goroutine 之间进行通信。

接口类型

  • 接口(Interface):一种抽象的类型,它定义了一组方法的集合。任何实现了这些方法的类型都满足这个接口。

函数类型

  • 函数(Function):在 Go 语言中,函数也是一种类型,可以被赋值给变量或作为参数传递给其他函数。

指针类型

  • 指针(Pointer):一个变量的地址。在 Go 语言中,可以使用指针来直接访问和操作内存中的数据。

其他基本类型

  • 字节切片(Byte Slice):通常用于处理字节数据,如读取文件或网络数据时。虽然字节切片不是一种独立的数据类型,但它在 Go 编程中非常常见。
  • runeruneint32 的别名,用于表示一个 Unicode 码点。它通常用于处理包含多字节字符的文本数据。
  • 复数类型(Complex Types):Go 语言支持两种复数类型:complex64complex128,分别对应 float32float64 的实部和虚部。

示例

以下是一些基本数据类型的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var i int     // 整型
var f float64 // 浮点型
var b bool    // 布尔型
var s string  // 字符串类型

var arr [5]int     // 数组类型
var slc []int      // 切片类型
var m map[string]int // 映射类型

var ch chan int     // 通道类型

func myFunc() {} // 函数类型

var ptr *int       // 指针类型

var c complex128   // 复数类型

var runeVar rune   // rune 类型,用于表示Unicode码点

变量

基本介绍

在 Go 语言(通常被称为 Golang)中,变量是用于存储数据的标识符。变量有一个名称(也称为标识符),一个类型和一个值。下面是一些关于 Golang 变量的基本介绍:

变量声明

在 Golang 中,变量在使用之前必须先声明。可以使用关键字var来声明变量,或者可以使用短变量声明操作符:=(这会自动推断变量的类型)。

  • 使用var声明

    1
    2
    3
    
    var name string
    var age int
    var isStudent bool
    
  • 使用短变量声明操作符:=(也称为类型推导)

    1
    2
    3
    
    name := "Alice"
    age := 30
    isStudent := true
    

    注意:使用:=声明的变量是自动初始化的,并且只能在函数内部使用(即它们是函数作用域的局部变量)。

变量类型

Golang 是一种静态类型语言,这意味着变量的类型在声明后不能更改。Golang 中的基本类型包括整数(如int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, byte等)、浮点数(如float32, float64)、复数(如complex64, complex128)、布尔值(bool)、字符串(string)等。此外,还有数组、切片、映射、通道和结构体等复合类型。

  • 变量初始化

    在声明变量时,可以使用赋值操作符=来初始化变量。如果声明了变量但没有初始化,那么它的值将是该类型的零值(例如,对于整数类型为 0,对于布尔类型为 false,对于字符串类型为空字符串”“等)。

  • 变量作用域和生命周期

    • 作用域:变量可以在其声明的代码块(例如函数或循环)中访问。在函数内部声明的变量是局部变量,它们在该函数执行完毕后将不再存在。在函数外部声明的变量是全局变量,可以在整个包(package)中访问。
    • 生命周期:变量的生命周期从它声明时开始,到其所在的代码块执行完毕时结束(对于局部变量)或程序结束时结束(对于全局变量)。在垃圾收集器运行期间,不再使用的变量所占用的内存将被自动释放。
  • 命名规范: 变量名应遵循一定的命名规范以提高代码的可读性和可维护性。通常,变量名应该使用驼峰命名法(camelCase),并且应该具有描述性以反映其用途。避免使用与 Golang 关键字或内置函数名相同的变量名。

完整例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main

import "fmt"

func main() {
    // 使用 var 关键字声明变量
    var name string
    var age int
    var isStudent bool

    // 初始化变量
    name = "Alice"
    age = 30
    isStudent = false

    // 使用 fmt 包打印变量值
    fmt.Println("Name:", name)
    fmt.Println("Age:", age)
    fmt.Println("Is Student:", isStudent)

    // 使用短变量声明操作符 :=
    grade := 90.5
    fmt.Println("Grade:", grade)

    // 声明并初始化一个字符串切片
    fruits := []string{"apple", "banana", "cherry"}
    fmt.Println("Fruits:", fruits)

    // 遍历切片
    for _, fruit := range fruits {
        fmt.Println(fruit)
    }

    // 声明并初始化一个映射(map)
    person := map[string]int{
        "Alice":   25,
        "Bob":     30,
        "Charlie": 35,
    }

    // 访问映射中的值
    fmt.Println("Bob's age from map:", person["Bob"])

    // 如果键不存在,返回该类型的零值
    fmt.Println("David's age from map (if exists):", person["David"])
}

在上面的示例中,我们展示了如何:

  • 使用 var 关键字声明变量,并后续初始化它们。
  • 使用短变量声明操作符 := 来声明并初始化变量(在这种情况下,Go 语言会自动推断变量的类型)。
  • 声明和初始化一个字符串切片(slice)并遍历它。
  • 声明和初始化一个映射(map),并访问其中的值。

注意,当我们尝试访问映射中不存在的键时(如 “David”),Go 语言会返回该类型的零值(在这种情况下是 int 类型的零值,即 0)。

iota

iota是一个预定义的标识符,用于创建自增的无类型整数常量。它通常用于枚举类型,为每个枚举值生成一个唯一的常量。iota的行为类似于一个计数器,每次在常量声明中出现时都会自增一次。

基本用法

iota在每个const关键字出现时被重置为 0,并在每个const块中为每个新声明的常量自增。如果在同一行声明了多个常量,则它们将共享相同的iota值,除非显式地给其中一个常量赋值。

使用示例

以下是一个使用iota来定义星期几的枚举类型的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "fmt"

func main() {
    const (
        Sunday = iota // iota 初始化为 0
        Monday        // iota 自增为 1
        Tuesday       // iota 自增为 2
        Wednesday     // iota 自增为 3
        Thursday      // iota 自增为 4
        Friday        // iota 自增为 5
        Saturday      // iota 自增为 6
    )

    fmt.Println(Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) // 输出: 0 1 2 3 4 5 6
}

在这个例子中,iota从 0 开始,并在每个新的常量声明中自动递增。因此,Sunday的值为 0,Monday的值为 1,依此类推。

递增规则

  • iota从 0 开始递增。
  • 每个const块中的iota值都会自动递增,不需要显式操作。
  • 在同一个const块中,每次遇到iota都会自增。
  • 在不同的const块中,iota会重新从 0 开始递增。

通过使用iota,可以简洁地定义一系列有序的常量,提高代码的可读性和可维护性。

特殊例子

展示iota的特殊情况,包括在同一行声明多个常量时如何共享相同的iota值,以及如何显式地给某个常量赋值以改变iota的自动递增。

特殊情况示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import "fmt"

func main() {
    const (
        // iota 在这里初始化为 0
        Sunday = iota // iota 值为 0
        Monday        // iota 值为 1
        Tuesday       // iota 值为 2

        // 显式赋值会改变 iota 的值
        WeekdayStart = Monday // WeekdayStart 值为 1,但 iota 仍然为 2

        // 同一行声明的常量共享相同的 iota 值
        Wednesday, Thursday = iota + 2, iota + 3 // Wednesday 值为 4,Thursday 值为 5

        // iota 继续自增
        Friday        // iota 值为 6
        Saturday      // iota 值为 7

        // 可以在新的 const 块中重置 iota
        const (
            firstQuarter = iota // iota 被重置为 0
            secondQuarter       // iota 值为 1
        )
    )

    fmt.Println(Sunday, Monday, Tuesday, WeekdayStart) // 输出: 0 1 2 1
    fmt.Println(Wednesday, Thursday, Friday, Saturday) // 输出: 4 5 6 7
    fmt.Println(firstQuarter, secondQuarter)          // 输出: 0 1
}

在这个例子中,首先定义了星期几的常量,并使用iota进行自动递增。然后,我们显式地将Monday的值赋给了WeekdayStart,但请注意,这并不会改变iota的自动递增行为,iota的值在赋值之后继续递增。

接下来,在同一行声明了WednesdayThursday,并为它们分别赋了iota + 2iota + 3的值。由于它们在同一行声明,所以它们都使用了同一个iota值(此时为 2),但加上了不同的偏移量。

最后,在一个新的const块中再次使用了iota,它会被重置为 0,并在该块中继续递增。

通过这个示例,可以看到iota的灵活性和在定义枚举或常量序列时的强大功能。

常量

在 Go 语言中,常量(Constants)是固定不变的值,它们在程序编译时被确定,并且在整个程序的执行过程中都不能被修改。常量可以是布尔值、数字(整数或浮点数)、字符串或枚举值。

常量的声明和初始化

在 Go 语言中,常量可以使用const关键字进行声明。你可以在同一行声明多个常量,如果它们具有相同的类型。如果常量的类型没有明确指定,那么 Go 编译器会根据常量的值来推断其类型。

以下是一些常量声明的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main

import "fmt"

func main() {
    // 声明并初始化单个常量
    const Pi = 3.14159

    // 在同一行声明多个相同类型的常量
    const (
        StatusOK    = 200
        StatusFound = 302
        StatusBad   = 400
    )

    // 使用 iota 进行递增的常量声明
    const (
        x = iota // x == 0
        y        // y == 1
        z        // z == 2
        wp       // 如果在这一行前没有显式赋值,则 wp 也会自增,wp == 3
    )

    // 显式赋值会改变 iota 的自增行为
    const (
        v = iota     // v == 0
        u = 100      // u == 100, iota 的自增被这个显式赋值打断了
        vv = iota    // vv == 1, iota 继续从上一个显式值开始自增
        ww = "hello" // ww 是字符串类型,iota 的自增被打断
        xx           // xx 在这里会是一个新的 iota 值,但它不会被使用(因为没有赋值给它)
    )

    fmt.Println(Pi)
    fmt.Println(StatusOK, StatusFound, StatusBad)
    fmt.Println(x, y, z, wp)
    // 注意:vv 和 ww 不会被打印,因为它们没有在这段代码中被使用
}

常量的类型

  • 数值常量:可以是整数或浮点数。
  • 布尔常量:可以是truefalse
  • 字符串常量:用双引号(")或反引号(```)括起来的字符序列。反引号中的字符串会原样输出,不进行转义。

常量的特点

  • 常量在声明时必须赋值。
  • 常量一旦被声明,其值就不能再改变。
  • 常量在编译时就已经确定,因此它们的值在运行时不会改变。
  • 常量可以是任何基本数据类型,也可以是数组、结构体和切片的组合类型,但不能是函数、映射或通道类型。

iota 枚举

iota是 Go 语言中的一个特殊常量,用于创建枚举值。在const声明中,iota会被自动赋值为 0,然后在每次新的const声明中自增 1。iota通常用于生成一组递增的整数常量。如上面示例中所示,你可以在同一行使用iota为多个常量赋值,或者在不同的行中使用iota来生成连续的整数常量。

This post is licensed under CC BY 4.0 by the author.