【Go-2】基本语法与数据类型

基本语法与数据类型

Go语言作为一种静态类型、编译型语言,拥有简洁且高效的语法结构。本章将深入介绍Go的基本语法和数据类型,帮助你建立扎实的编程基础。

2.1 第一个 Go 程序

编写第一个Go程序是学习任何编程语言的传统步骤。通过一个简单的"Hello, World!"程序,你将了解Go程序的基本结构和运行方式。

main 函数

每个Go程序的执行都从main包的main函数开始。main函数是程序的入口点,定义了程序启动时执行的代码。

示例:

go 复制代码
package main

func main() {
    // 程序入口
}
  • package main: 声明当前文件属于main包。main包是可执行程序的入口包。
  • func main(): 定义main函数,这是程序的起始点。
fmt.Println() 输出

fmt包是Go的标准输入输出包,提供了格式化的I/O函数。fmt.Println()用于在控制台输出文本并换行。

完整的"Hello, World!"程序:

go 复制代码
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

解释:

  • import "fmt": 导入fmt包,以便使用其提供的函数。
  • fmt.Println("Hello, World!"): 输出字符串"Hello, World!"到控制台,并换行。

运行程序:

  1. 保存文件为hello.go

  2. 在终端中导航到文件所在目录。

  3. 执行命令:

    复制代码
    go run hello.go
  4. 输出:

    复制代码
    Hello, World!

编译并运行:

  1. 编译程序:

    复制代码
    go build hello.go

    这将生成一个可执行文件

    复制代码
    hello

    (在Windows上为

    复制代码
    hello.exe

    )。

  2. 运行可执行文件:

    复制代码
    ./hello
  3. 输出:

    复制代码
    Hello, World!

2.2 变量与常量

变量和常量是编程语言中存储和管理数据的基本单元。Go语言提供了多种方式来声明和使用变量和常量。

声明变量

在Go中,变量使用var关键字声明,后跟变量名和类型。

示例:

go 复制代码
var age int
age = 30

var name string
name = "Alice"

也可以在声明时赋值:

go 复制代码
var age int = 30
var name string = "Alice"

Go支持类型推断,即编译器可以根据赋值自动推断变量类型:

go 复制代码
var age = 30          // age为int
var name = "Alice"    // name为string
短变量声明

在函数内部,可以使用短变量声明语法:=来声明并初始化变量,而无需显式指定类型。

示例:

go 复制代码
age := 30
name := "Alice"
isStudent := true

等同于:

go 复制代码
var age int = 30
var name string = "Alice"
var isStudent bool = true
常量与枚举

常量使用const关键字声明,其值在编译时确定,且不可修改。

示例:

go 复制代码
const Pi = 3.14159
const Greeting = "Hello, World!"

Go不直接支持枚举类型,但可以使用常量组合iota来模拟枚举。

示例:

go 复制代码
const (
    Sunday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
)

解释:

  • iota是Go的一个预声明标识符,表示常量组中的索引,从0开始。
  • 上述代码定义了一组代表星期的常量,分别为0到6。

使用枚举模拟:

go 复制代码
package main

import "fmt"

const (
    Red = iota
    Green
    Blue
)

func main() {
    fmt.Println(Red)    // 输出: 0
    fmt.Println(Green)  // 输出: 1
    fmt.Println(Blue)   // 输出: 2
}

2.3 数据类型

Go语言提供了多种数据类型,分为基本类型和复合类型。掌握这些数据类型是编写有效Go程序的基础。

基本类型
整型

Go支持多种整型,包括有符号和无符号类型,以及不同位数的类型。

  • 有符号整型:int8, int16, int32, int64, int
  • 无符号整型:uint8, uint16, uint32, uint64, uint
    示例:
go 复制代码
var a int = 10
var b int64 = 10000000000
var c uint = 20
var d uint8 = 255
浮点型

Go支持float32float64两种浮点类型。

示例:

go 复制代码
var pi float32 = 3.14
var e float64 = 2.718281828459045
字符串

字符串是由字符组成的序列,使用双引号"或反引号```包裹。

示例:

go 复制代码
var greeting string = "Hello, World!"
var multiline string = `This is a
multiline string.`

字符串是不可变的,无法直接修改单个字符。

布尔型

布尔类型表示真或假,使用bool类型。

示例:

go 复制代码
var isGoFun bool = true
var isStudent bool = false
复合类型

复合类型是由多个基本类型组成的类型,包括数组、切片、Map、结构体和指针。

数组

数组是具有固定大小和相同类型元素的有序集合。

声明和初始化:

go 复制代码
var arr [5]int
arr[0] = 10
arr[1] = 20

// 声明并初始化
var arr2 = [3]string{"apple", "banana", "cherry"}

// 使用省略长度
arr3 := [...]float64{1.1, 2.2, 3.3}

遍历数组:

go 复制代码
for i, v := range arr2 {
    fmt.Printf("Index: %d, Value: %s\n", i, v)
}
切片

切片是基于数组的动态数据结构,比数组更灵活和强大。切片的长度和容量可以动态变化。

声明和初始化:

go 复制代码
// 空切片
var s []int

// 使用make函数
s1 := make([]int, 5) // 长度为5,元素初始化为0
s2 := make([]int, 3, 10) // 长度为3,容量为10

// 字面量初始化
s3 := []string{"Go", "Python", "Java"}

添加元素:

go 复制代码
s4 := []int{1, 2, 3}
s4 = append(s4, 4, 5)

切片截取:

go 复制代码
s5 := []int{1, 2, 3, 4, 5}
sub := s5[1:3] // 包含索引1和2,不包含3
fmt.Println(sub) // 输出: [2 3]

切片的底层原理: 切片由指向数组的指针、长度和容量组成。切片的容量表示从切片的起始位置到底层数组末尾的元素数量。

Map

Map是键值对的无序集合,键和值可以是不同的类型。Map在Go中作为内置数据类型提供,类似于Python的字典或Java的HashMap。

声明和初始化:

go 复制代码
// 声明为空Map
var m map[string]int

// 使用make初始化
m = make(map[string]int)

// 声明并初始化
m1 := map[string]int{
    "apple":  5,
    "banana": 3,
}

// 使用简短声明
m2 := make(map[string]string)

添加和访问元素:

go 复制代码
m["orange"] = 7
value := m["apple"]
fmt.Println("apple:", value)

删除元素:

go 复制代码
delete(m, "banana")

检查键是否存在:

go 复制代码
value, exists := m["banana"]
if exists {
    fmt.Println("banana exists with value:", value)
} else {
    fmt.Println("banana does not exist")
}

遍历Map:

go 复制代码
for key, value := range m {
    fmt.Printf("Key: %s, Value: %d\n", key, value)
}
结构体

结构体是由多个字段组成的复合数据类型,可以包含不同类型的数据。

定义和使用结构体:

go 复制代码
type Person struct {
    Name string
    Age  int
}

func main() {
    var p Person
    p.Name = "Alice"
    p.Age = 30

    // 使用字面量初始化
    p2 := Person{Name: "Bob", Age: 25}

    fmt.Println(p)
    fmt.Println(p2)
}

嵌套结构体:

go 复制代码
type Address struct {
    City    string
    ZipCode string
}

type Employee struct {
    Person
    Address
    Position string
}

func main() {
    e := Employee{
        Person:   Person{Name: "Charlie", Age: 28},
        Address:  Address{City: "New York", ZipCode: "10001"},
        Position: "Developer",
    }

    fmt.Println(e)
    fmt.Println("City:", e.Address.City)
}

方法与结构体:

Go支持为结构体类型定义方法。

go 复制代码
type Rectangle struct {
    Width, Height float64
}

// 方法接收者为指针类型
func (r *Rectangle) Area() float64 {
    return r.Width * r.Height
}

func main() {
    rect := Rectangle{Width: 10, Height: 5}
    fmt.Println("Area:", rect.Area())
}
指针

指针是存储变量内存地址的变量。Go中使用指针可以提高程序的性能,避免大量数据的复制。

声明和使用指针:

go 复制代码
func main() {
    var a int = 10
    var p *int = &a // p指向a的地址

    fmt.Println("a:", a)       // 输出: a: 10
    fmt.Println("p:", p)       // 输出: p: 地址值
    fmt.Println("*p:", *p)     // 输出: *p: 10

    *p = 20 // 通过指针修改a的值
    fmt.Println("a after:", a) // 输出: a after: 20
}

指针与函数:

使用指针作为函数参数,可以在函数中修改传入的变量。

go 复制代码
func increment(n *int) {
    *n += 1
}

func main() {
    a := 5
    increment(&a)
    fmt.Println("a after increment:", a) // 输出: a after increment: 6
}

2.4 类型转换

在Go中,不同类型之间的转换需要显式进行,称为类型转换。Go不支持隐式类型转换,以确保类型安全。

语法:

go 复制代码
var x int = 10
var y float64 = float64(x)

示例:

go 复制代码
package main

import "fmt"

func main() {
    // 整型与浮点型转换
    var a int = 5
    var b float64 = float64(a)
    var c int = int(b) // 会截断小数部分

    fmt.Println(a, b, c) // 输出: 5 5.0 5

    // 字符串与字节切片转换
    str := "Hello"
    bytes := []byte(str)
    str2 := string(bytes)

    fmt.Println(str, bytes, str2) // 输出: Hello [72 101 108 108 111] Hello

    // 类型之间的转换示例:int到string(需要转换为字符)
    num := 65
    char := string(num)
    fmt.Println(char) // 输出: 'A'
}

注意事项:

  • 只能在兼容类型之间转换,如整数类型之间、浮点类型之间。
  • 字符串与字节切片之间的转换需要使用[]bytestring类型转换。
  • 类型转换可能导致数据丢失,如将float64转换为int会截断小数部分。

更多示例:

go 复制代码
// 将int转换为float64
var i int = 42
var f float64 = float64(i)
fmt.Println(f) // 输出: 42

// 将float64转换为int
var j float64 = 3.14
var k int = int(j)
fmt.Println(k) // 输出: 3

// 将string转换为[]rune
str := "你好"
runes := []rune(str)
fmt.Println(runes) // 输出: [20320 22909]

// 将[]rune转换为string
str2 := string(runes)
fmt.Println(str2) // 输出: 你好

类型转换与算术运算:

在进行算术运算时,操作数必须是相同类型。否则,需要先进行类型转换。

示例:

go 复制代码
package main

import "fmt"

func main() {
    var a int = 10
    var b float64 = 3.14

    // 错误:不能直接相加不同类型
    // c := a + b

    // 正确:先转换类型
    c := float64(a) + b
    fmt.Println(c) // 输出: 13.14
}
相关推荐
Luis Li 的猫猫2 分钟前
MATLAB跳动的爱心
开发语言·算法·matlab
AIGC魔法师21 分钟前
AI 极客低代码平台快速上手 --生成Python代码
开发语言·harmonyos·低代码平台·ai极客
熊猫钓鱼>_>35 分钟前
对话即编程:如何用 Trae 的 @智能体 5 分钟修复一个复杂 Bug?
开发语言·python·bug
搏博38 分钟前
WPS JS宏实现去掉文档中的所有空行
开发语言·javascript·wps
hie9889443 分钟前
MATLAB中进行语音信号分析
开发语言·matlab·语音识别
前进的程序员1 小时前
C++经典库介绍
开发语言·c++
heart000_11 小时前
Go 语言云原生微服务全栈实战:Docker 镜像优化、K8s 编排与 Istio 流量治理
微服务·云原生·golang
(・Д・)ノ2 小时前
python打卡day31
开发语言·人工智能·python
北漂老男孩2 小时前
JavaScript 性能优化实战指南
开发语言·javascript·性能优化
yorushika_2 小时前
python打卡训练营打卡记录day31
开发语言·python·机器学习