Go Fundamentals 是更多的Go基础知识,涵盖了数据结构(基础数据结构、数组、slice、map)、语言基础(函数、接口、反射)、关键字和并发等方面。掌握这些概念和技术将帮助您编写高效、可靠和复杂的Go程序。
数据结构
数据类型(Data Types):
- Go语言有基本数据类型,包括布尔型、数字型、字符串和字符型。
- 可以使用var关键字来声明变量,也可以使用:=运算符进行变量初始化和类型推断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// 声明变量 var age int var name string var isMarried bool // 初始化变量 age = 30 name = "Alice" isMarried = true // 自动类型推断 age := 30 name := "Alice" isMarried := true
数组和切片(Arrays and Slices):
- Go语言有数组和切片两种类型,用于存储元素的序列。
- 数组是固定长度的序列,可以通过索引来访问元素。
- 切片是动态长度的序列,可以使用append函数来添加元素。
1 2 3 4 5 6 7 8 9 10 11
// 定义数组和切片 numbers := [5]int{1, 2, 3, 4, 5} letters := []string{"A", "B", "C"} // 访问数组元素 fmt.Println(numbers[0]) fmt.Println(numbers[3]) // 添加切片元素 letters = append(letters, "D") fmt.Println(letters)
映射(Maps):
- Go语言使用映射来存储键值对。
- 可以使用make函数创建映射,使用[]运算符访问键值对。
- 映射是无序的,但是可以使用range关键字迭代映射中的所有键值对。
1 2 3 4 5 6 7 8 9 10 11 12 13
// 创建映射 ages := make(map[string]int) ages["Alice"] = 30 ages["Bob"] = 25 // 访问映射元素 fmt.Println(ages["Alice"]) fmt.Println(ages["Bob"]) // 迭代映射 for name, age := range ages { fmt.Println(name, age) }
语言基础
控制结构(Control Structures):
- Go语言有if/else语句、for循环、switch语句等控制结构。
- if/else语句可以嵌套,可以用来检查多个条件。
- for循环可以用来迭代数组、切片和映射,也可以用来执行无限循环。
- switch语句可以用来匹配多个表达式的值。
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
// if/else语句 if age > 18 { fmt.Println("You are an adult") } else if age > 12 { fmt.Println("You are a teenager") } else { fmt.Println("You are a child") } // for循环 for i := 0; i < 5; i++ { fmt.Println(i) } // 迭代数组 numbers := []int{1, 2, 3, 4, 5} for _, number := range numbers { fmt.Println(number) } // switch语句 switch age { case 0: fmt.Println("You are a baby") case 1, 2: fmt.Println("You are a toddler") case 3, 4, 5: fmt.Println("You are a preschooler") default: fmt.Println("You are not young anymore") }
函数(Functions):
- 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
// 定义函数 func add(a, b int) int { return a + b } // 调用函数 sum := add(1, 2) fmt.Println(sum) // 返回多个值 func divide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("Division by zero") } return a / b, nil } result, err := divide(10.0, 0.0) if err != nil { fmt.Println(err) } else { fmt.Println(result) } // 匿名函数和闭包 func increase() func() int { i := 0 return func() int { i += 1 return i } } counter := increase() fmt.Println(counter()) // 1 fmt.Println(counter()) // 2
结构体(Structs):
- Go语言使用结构体来定义自定义类型。
- 结构体由字段(field)组成,每个字段都有一个名称和类型。
- 可以使用点操作符来访问结构体的字段。
1 2 3 4 5 6 7 8 9 10 11 12
// 定义结构体 type Person struct { Name string Age int } // 创建结构体实例 person := Person{Name: "Alice", Age: 30} // 访问结构体字段 fmt.Println(person.Name) fmt.Println(person.Age)
指针(Pointers):
- Go语言具有指针类型,用于指向变量的内存地址。
- 可以使用&运算符来获取变量的地址,使用*运算符来访问指针指向的值。
1 2 3 4 5 6 7 8 9
// 定义指针变量 var agePointer *int // 获取变量的地址,并将地址赋值给指针变量 age := 30 agePointer = &age // 通过指针访问变量的值 fmt.Println(*agePointer) // 输出30
方法(Methods):
- Go语言中的方法是一种特殊类型的函数,它与结构体关联在一起。
- 方法可以在结构体上定义,并且可以通过结构体的实例调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// 定义结构体 type Rectangle struct { width float64 height float64 } // 定义方法 func (r Rectangle) Area() float64 { return r.width * r.height } // 创建结构体实例 rectangle := Rectangle{width: 10, height: 5} // 调用方法 area := rectangle.Area() fmt.Println(area)
接口(Interfaces):
- 接口是一种抽象类型,它定义了一组方法的集合。
- 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
// 定义接口 type Shape interface { Area() float64 } // 实现接口 type Rectangle struct { width float64 height float64 } func (r Rectangle) Area() float64 { return r.width * r.height } // 创建接口类型的变量 var shape Shape // 将结构体实例赋给接口变量 shape = Rectangle{width: 10, height: 5} // 调用接口方法 area := shape.Area() fmt.Println(area)
关键字
select:用于选择不同的通信操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
c1 := make(chan int) c2 := make(chan string) go func() { time.Sleep(1 * time.Second) c1 <- 10 }() go func() { time.Sleep(2 * time.Second) c2 <- "Hello" }() select { case i := <-c1: fmt.Println("Received from c1:", i) case s := <-c2: fmt.Println("Received from c2:", s) }
panic:用于抛出一个运行时异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
func divide(a, b int) int { if b == 0 { panic("division by zero") } return a / b } func main() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered from panic:", r) } }() result := divide(10, 0) fmt.Println("Result:", result) }
recover:用于恢复一个运行时异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
func divide(a, b int) int { if b == 0 { panic("division by zero") } return a / b } func main() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered from panic:", r) } }() result := divide(10, 0) fmt.Println("Result:", result) }
make:用于创建一个切片、映射或通道等引用类型的对象。
1 2 3 4 5 6 7 8 9 10 11
s := make([]int, 3) fmt.Println(s) m := make(map[string]int) m["one"] = 1 m["two"] = 2 fmt.Println(m) c := make(chan int, 1) c <- 10 fmt.Println(<-c)
new:用于创建一个值类型的对象并返回其指针。
1 2 3 4 5
p := new(int) fmt.Println(*p) *p = 10 fmt.Println(*p)
defer:用于延迟执行一个函数,通常用于释放资源或恢复状态等操作。
1 2 3 4
func main() { defer fmt.Println("This will be printed last") fmt.Println("This will be printed first") }
switch:用于基于不同条件执行不同的代码块。
1 2 3 4 5 6 7 8 9 10
day := "Monday" switch day { case "Monday": fmt.Println("Today is Monday") case "Tuesday": fmt.Println("Today is Tuesday") default: fmt.Println("Today is another day") }
range:用于遍历数组、切片、映射等数据结构。
1 2 3 4 5 6 7 8 9
numbers := []int{1, 2, 3, 4, 5} for index, value := range numbers { fmt.Println(index, value) } for key, value := range m { fmt.Println(key, value) }
并发
并发(Concurrency):
- Go语言内置支持并发编程,使用goroutine和channel来实现。
- goroutine是一种轻量级的线程,可以同时执行多个任务。
- channel是用于goroutine之间通信的管道,可以发送和接收数据。
1 2 3 4 5 6 7 8 9 10 11 12
// 创建goroutine go func() { fmt.Println("Hello from goroutine!") }() // 创建有缓冲的channel ch := make(chan int, 1) // 发送和接收数据 ch <- 10 result := <- ch fmt.Println(result)
以上是Go Fundamentals的简要介绍和代码举例。这些基本概念是Go编程的核心,熟练掌握它们可以帮助您编写清晰、高效和可读性强的代码。