MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Go语言基本数据类型概览

2024-03-172.1k 阅读

整数类型

在Go语言中,整数类型根据其大小和有无符号进行分类。

有符号整数

  1. int8:8位有符号整数,取值范围是 -128 到 127。它在内存中占用1个字节。例如:
package main

import (
    "fmt"
)

func main() {
    var num int8 = -128
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)
}
  1. int16:16位有符号整数,取值范围是 -32768 到 32767。它在内存中占用2个字节。示例如下:
package main

import (
    "fmt"
)

func main() {
    var num int16 = -32768
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)
}
  1. int32:32位有符号整数,取值范围是 -2147483648 到 2147483647。它在内存中占用4个字节。在Go语言中,runeint32 的别名,常用于表示Unicode码点。例如:
package main

import (
    "fmt"
)

func main() {
    var num int32 = -2147483648
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)

    var char rune = '中'
    fmt.Printf("The character is %c, and its code point is %d\n", char, char)
}
  1. int64:64位有符号整数,取值范围是 -9223372036854775808 到 9223372036854775807。它在内存中占用8个字节。示例代码:
package main

import (
    "fmt"
)

func main() {
    var num int64 = -9223372036854775808
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)
}
  1. int:它的大小取决于运行程序的操作系统平台,在32位系统上是32位,在64位系统上是64位。使用 int 类型可以避免因平台差异而导致的代码不兼容问题。例如:
package main

import (
    "fmt"
)

func main() {
    var num int = 100
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)
}

无符号整数

  1. uint8:8位无符号整数,取值范围是 0 到 255。它在内存中占用1个字节,byteuint8 的别名,常用于处理字节数据。示例如下:
package main

import (
    "fmt"
)

func main() {
    var num uint8 = 255
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)

    var byteValue byte = 'A'
    fmt.Printf("The byte value is %d, and the character is %c\n", byteValue, byteValue)
}
  1. uint16:16位无符号整数,取值范围是 0 到 65535。它在内存中占用2个字节。例如:
package main

import (
    "fmt"
)

func main() {
    var num uint16 = 65535
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)
}
  1. uint32:32位无符号整数,取值范围是 0 到 4294967295。它在内存中占用4个字节。示例代码:
package main

import (
    "fmt"
)

func main() {
    var num uint32 = 4294967295
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)
}
  1. uint64:64位无符号整数,取值范围是 0 到 18446744073709551615。它在内存中占用8个字节。例如:
package main

import (
    "fmt"
)

func main() {
    var num uint64 = 18446744073709551615
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)
}
  1. uint:与 int 类似,其大小取决于操作系统平台,在32位系统上是32位,在64位系统上是64位。例如:
package main

import (
    "fmt"
)

func main() {
    var num uint = 100
    fmt.Printf("The value of num is %d, and its type is %T\n", num, num)
}

浮点型

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

float32

float32 是32位的浮点数,它遵循IEEE 754标准。其精度大约是6 - 7位十进制数字。示例如下:

package main

import (
    "fmt"
)

func main() {
    var num1 float32 = 3.1415926
    fmt.Printf("The value of num1 is %f, and its type is %T\n", num1, num1)
}

由于 float32 的精度有限,在进行一些需要高精度的计算时可能会出现精度丢失问题。例如:

package main

import (
    "fmt"
)

func main() {
    var a float32 = 1.23456789
    var b float32 = 0.98765432
    var result float32 = a + b
    fmt.Printf("The result of a + b is %f\n", result)
}

在这个例子中,计算结果可能与预期的精确值有一定偏差。

float64

float64 是64位的浮点数,同样遵循IEEE 754标准。其精度大约是15 - 17位十进制数字。在大多数情况下,建议使用 float64,因为它提供了更高的精度。示例代码:

package main

import (
    "fmt"
)

func main() {
    var num2 float64 = 3.141592653589793
    fmt.Printf("The value of num2 is %f, and its type is %T\n", num2, num2)
}

在进行科学计算或需要高精度的数值计算时,float64 能更好地满足需求。例如:

package main

import (
    "fmt"
    "math"
)

func main() {
    var radius float64 = 5.0
    var area float64 = math.Pi * math.Pow(radius, 2)
    fmt.Printf("The area of the circle is %f\n", area)
}

复数类型

Go语言提供了两种复数类型:complex64complex128

complex64

complex64 表示实部和虚部都是 float32 类型的复数,在内存中占用8个字节。可以通过 complex 函数来创建复数,或者直接使用字面量。例如:

package main

import (
    "fmt"
)

func main() {
    var c1 complex64 = complex(3.0, 4.0)
    var c2 complex64 = 3 + 4i
    fmt.Printf("c1: %v, type: %T\n", c1, c1)
    fmt.Printf("c2: %v, type: %T\n", c2, c2)
}

可以使用 real 函数获取复数的实部,使用 imag 函数获取复数的虚部。例如:

package main

import (
    "fmt"
)

func main() {
    var c complex64 = 3 + 4i
    fmt.Printf("Real part: %f\n", real(c))
    fmt.Printf("Imaginary part: %f\n", imag(c))
}

complex128

complex128 表示实部和虚部都是 float64 类型的复数,在内存中占用16个字节。它提供了更高的精度,适用于对精度要求较高的复数运算。例如:

package main

import (
    "fmt"
)

func main() {
    var c1 complex128 = complex(3.141592653589793, 2.718281828459045)
    var c2 complex128 = 3.141592653589793 + 2.718281828459045i
    fmt.Printf("c1: %v, type: %T\n", c1, c1)
    fmt.Printf("c2: %v, type: %T\n", c2, c2)
}

同样可以使用 realimag 函数获取实部和虚部:

package main

import (
    "fmt"
)

func main() {
    var c complex128 = 3.141592653589793 + 2.718281828459045i
    fmt.Printf("Real part: %f\n", real(c))
    fmt.Printf("Imaginary part: %f\n", imag(c))
}

布尔类型

布尔类型 bool 只有两个值:truefalse。它常用于条件判断和逻辑运算。例如:

package main

import (
    "fmt"
)

func main() {
    var isTrue bool = true
    var isFalse bool = false

    fmt.Printf("isTrue: %v, type: %T\n", isTrue, isTrue)
    fmt.Printf("isFalse: %v, type: %T\n", isFalse, isFalse)

    result := isTrue && isFalse
    fmt.Printf("The result of isTrue && isFalse is %v\n", result)
}

在Go语言中,布尔值不能与其他类型进行隐式转换,例如不能将 bool 类型的值转换为数字类型。

字符串类型

字符串在Go语言中是一个不可变的字节序列。它通常用于表示文本数据。

字符串字面量

可以使用双引号 " 来创建字符串字面量。例如:

package main

import (
    "fmt"
)

func main() {
    var str1 string = "Hello, World!"
    fmt.Printf("str1: %v, type: %T\n", str1, str1)
}

字符串可以包含转义字符,例如 \n 表示换行,\t 表示制表符等。例如:

package main

import (
    "fmt"
)

func main() {
    var str2 string = "Hello\nWorld!"
    fmt.Println(str2)
}

还可以使用反引号 ``` 来创建原生字符串字面量,其中的转义字符不会被解释。例如:

package main

import (
    "fmt"
)

func main() {
    var str3 string = `Hello\nWorld!`
    fmt.Println(str3)
}

字符串操作

  1. 字符串拼接:可以使用 + 运算符来拼接字符串。例如:
package main

import (
    "fmt"
)

func main() {
    var str1 string = "Hello"
    var str2 string = " World"
    var result string = str1 + str2
    fmt.Println(result)
}
  1. 字符串长度:可以使用 len 函数获取字符串的字节长度。需要注意的是,如果字符串包含非ASCII字符,len 函数返回的是字节数,而不是字符数。例如:
package main

import (
    "fmt"
)

func main() {
    var str string = "Hello"
    fmt.Printf("The length of str is %d\n", len(str))

    var chineseStr string = "中国"
    fmt.Printf("The length of chineseStr is %d\n", len(chineseStr))
}

要获取字符串的字符数,可以将字符串转换为 rune 切片。例如:

package main

import (
    "fmt"
)

func main() {
    var chineseStr string = "中国"
    runes := []rune(chineseStr)
    fmt.Printf("The number of characters in chineseStr is %d\n", len(runes))
}
  1. 字符串索引:可以通过索引访问字符串的字节,但不能直接修改字符串的某个字节,因为字符串是不可变的。例如:
package main

import (
    "fmt"
)

func main() {
    var str string = "Hello"
    fmt.Printf("The first byte of str is %c\n", str[0])
}
  1. 字符串遍历:可以使用 for 循环来遍历字符串。如果要按字符遍历,建议使用 rune 类型。例如:
package main

import (
    "fmt"
)

func main() {
    var str string = "中国"
    for _, char := range str {
        fmt.Printf("%c ", char)
    }
    fmt.Println()
}

字节类型与rune类型

字节类型 byteuint8 的别名,常用于处理字节数据,例如在文件读取、网络通信等场景中。而 runeint32 的别名,用于表示Unicode码点,处理多字节字符时非常有用。

byte类型

当处理纯字节数据,如二进制文件、网络协议数据等,byte 类型是首选。例如,读取一个文件并将其内容以字节形式输出:

package main

import (
    "fmt"
    "os"
)

func main() {
    data, err := os.ReadFile("test.txt")
    if err != nil {
        fmt.Println("Error reading file:", err)
        return
    }
    for _, byteValue := range data {
        fmt.Printf("%02X ", byteValue)
    }
    fmt.Println()
}

rune类型

在处理包含非ASCII字符的文本时,rune 类型能确保正确地处理每个字符。例如,统计字符串中的中文字符个数:

package main

import (
    "fmt"
)

func main() {
    var str string = "Hello中国"
    count := 0
    for _, char := range str {
        if char >= '\u4e00' && char <= '\u9fff' {
            count++
        }
    }
    fmt.Printf("The number of Chinese characters is %d\n", count)
}

数组类型

数组是Go语言中一种基本的数据结构,它是具有固定大小且类型相同的元素序列。

数组声明与初始化

  1. 声明数组:可以使用以下方式声明一个数组:
package main

import (
    "fmt"
)

func main() {
    var numbers [5]int
    fmt.Println(numbers)
}

这里声明了一个包含5个 int 类型元素的数组,初始值为0。 2. 初始化数组:可以在声明时初始化数组。例如:

package main

import (
    "fmt"
)

func main() {
    var numbers [5]int = [5]int{1, 2, 3, 4, 5}
    fmt.Println(numbers)
}

也可以使用简短声明方式:

package main

import (
    "fmt"
)

func main() {
    numbers := [5]int{1, 2, 3, 4, 5}
    fmt.Println(numbers)
}

还可以省略数组大小,让编译器根据初始化值的数量来推断:

package main

import (
    "fmt"
)

func main() {
    numbers := [...]int{1, 2, 3, 4, 5}
    fmt.Println(numbers)
}

数组访问与遍历

  1. 访问数组元素:可以通过索引访问数组元素,索引从0开始。例如:
package main

import (
    "fmt"
)

func main() {
    numbers := [5]int{1, 2, 3, 4, 5}
    fmt.Printf("The first element is %d\n", numbers[0])
}
  1. 遍历数组:可以使用 for 循环遍历数组。例如:
package main

import (
    "fmt"
)

func main() {
    numbers := [5]int{1, 2, 3, 4, 5}
    for i := 0; i < len(numbers); i++ {
        fmt.Printf("Element at index %d is %d\n", i, numbers[i])
    }
}

还可以使用 for - range 循环,它会同时返回索引和元素值:

package main

import (
    "fmt"
)

func main() {
    numbers := [5]int{1, 2, 3, 4, 5}
    for index, value := range numbers {
        fmt.Printf("Index: %d, Value: %d\n", index, value)
    }
}

切片类型

切片是基于数组构建的动态数据结构,它提供了一种灵活且高效的方式来处理一组相同类型的数据。

切片创建

  1. 基于数组创建切片:可以通过从数组中截取一部分来创建切片。例如:
package main

import (
    "fmt"
)

func main() {
    numbers := [5]int{1, 2, 3, 4, 5}
    slice1 := numbers[1:3]
    fmt.Println(slice1)
}

这里从 numbers 数组的索引1开始截取到索引3(不包含索引3),创建了一个新的切片 slice1。 2. 使用make函数创建切片make 函数可以直接创建切片。例如:

package main

import (
    "fmt"
)

func main() {
    slice2 := make([]int, 3)
    fmt.Println(slice2)
}

这里创建了一个长度为3的 int 类型切片,初始值为0。make 函数还可以指定切片的容量:

package main

import (
    "fmt"
)

func main() {
    slice3 := make([]int, 3, 5)
    fmt.Printf("Length: %d, Capacity: %d\n", len(slice3), cap(slice3))
}

切片操作

  1. 切片追加元素:可以使用 append 函数向切片中追加元素。例如:
package main

import (
    "fmt"
)

func main() {
    slice := []int{1, 2, 3}
    slice = append(slice, 4)
    fmt.Println(slice)
}

如果切片的容量不足以容纳新元素,append 函数会自动重新分配内存,扩大切片的容量。 2. 切片复制:可以使用 copy 函数将一个切片的内容复制到另一个切片。例如:

package main

import (
    "fmt"
)

func main() {
    source := []int{1, 2, 3}
    destination := make([]int, len(source))
    copy(destination, source)
    fmt.Println(destination)
}

映射类型

映射(map)是Go语言中的一种无序键值对集合,它提供了快速的查找和插入操作。

映射创建与初始化

  1. 使用make函数创建映射:可以使用 make 函数创建映射。例如:
package main

import (
    "fmt"
)

func main() {
    scores := make(map[string]int)
    scores["Alice"] = 85
    scores["Bob"] = 90
    fmt.Println(scores)
}
  1. 使用字面量初始化映射:也可以使用字面量方式初始化映射。例如:
package main

import (
    "fmt"
)

func main() {
    scores := map[string]int{
        "Alice": 85,
        "Bob":   90,
    }
    fmt.Println(scores)
}

映射操作

  1. 获取值:可以通过键获取对应的值。例如:
package main

import (
    "fmt"
)

func main() {
    scores := map[string]int{
        "Alice": 85,
        "Bob":   90,
    }
    score, exists := scores["Alice"]
    if exists {
        fmt.Printf("Alice's score is %d\n", score)
    } else {
        fmt.Println("Alice's score not found")
    }
}
  1. 删除键值对:可以使用 delete 函数删除映射中的键值对。例如:
package main

import (
    "fmt"
)

func main() {
    scores := map[string]int{
        "Alice": 85,
        "Bob":   90,
    }
    delete(scores, "Bob")
    fmt.Println(scores)
}

结构体类型

结构体是一种自定义的数据类型,它允许将不同类型的数据组合在一起。

结构体定义与初始化

  1. 结构体定义:可以使用 struct 关键字定义结构体。例如:
package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}
  1. 结构体初始化:可以使用以下方式初始化结构体:
package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    person1 := Person{
        Name: "Alice",
        Age:  25,
    }
    fmt.Println(person1)
}

也可以使用 new 函数创建结构体指针并初始化:

package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    person2 := new(Person)
    person2.Name = "Bob"
    person2.Age = 30
    fmt.Println(person2)
}

结构体字段访问

可以通过结构体实例或结构体指针来访问结构体的字段。例如:

package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    person := Person{
        Name: "Alice",
        Age:  25,
    }
    fmt.Printf("Name: %s, Age: %d\n", person.Name, person.Age)

    personPtr := &person
    fmt.Printf("Name: %s, Age: %d\n", personPtr.Name, personPtr.Age)
}

指针类型

指针是一个变量,其值为另一个变量的地址。在Go语言中,指针可以用于传递数据的引用,从而避免在函数调用时进行大量的数据复制。

指针声明与使用

  1. 指针声明:可以使用 * 运算符声明指针。例如:
package main

import (
    "fmt"
)

func main() {
    var num int = 10
    var ptr *int = &num
    fmt.Printf("The value of num is %d\n", num)
    fmt.Printf("The address of num is %p\n", &num)
    fmt.Printf("The value of ptr is %p\n", ptr)
    fmt.Printf("The value pointed by ptr is %d\n", *ptr)
}
  1. 指针作为函数参数:指针可以作为函数参数,使函数能够修改调用者传入的变量的值。例如:
package main

import (
    "fmt"
)

func increment(ptr *int) {
    *ptr++
}

func main() {
    var num int = 10
    increment(&num)
    fmt.Printf("The value of num after increment is %d\n", num)
}

通过对以上Go语言基本数据类型的详细介绍,开发者可以更深入地理解和运用这些数据类型,从而编写出高效、健壮的Go语言程序。在实际开发中,根据具体的需求选择合适的数据类型是非常重要的,它直接影响到程序的性能和可读性。同时,不同数据类型之间的相互转换以及在复杂数据结构中的组合使用,也是需要不断实践和掌握的关键技能。