跳到主要内容

《Go 语言圣经》

书籍地址:https://golang-china.github.io/gopl-zh/index.html

内置包

flag

flag 包提供了一种解析命令行选项和参数的方法

  • flag.Bool var n = flag.Bool("n", false, "omit frailing newline")
  • flag.String var sep = flag.String("s"," ","separator")

range

go 的关键字,用于迭代各种数据结构

1、数组

numbers := []int {1,2,3,4,5}
for index,value := range numbers {
fmt.Printf("Index: %d, Value: %d",index,value)
}
如果只需获取值,可以使用空白标识符 _ 来忽略索引
for _,value := range numbers{
fmt.Printf("Value: %d",value)
}

2、字符串

str := "hello,world"
for index,runeValue := range str {
fmt.Printf("Index: %d,Rune: %c",index,runeValue)
}

3、map

m := map[string]int{"a":1,"b":2,"c":3}
for key,value := range str {
fmt.Printf("Key: %d,Value: %c",key,value)
}

4、channel

ch := make(chan int,5)
go func(){
ch <- 1
ch <- 2
ch <- 3
close(ch)
}()

for value := range ch{
fmt.Printf("Received:" value)
}

math

  • math.Exp(x float64) e的x次幂
  • math.NaN 返回一个“非数”(NaN)
  • math.IsNaN 测试一个数是不是 NaN
  • math.Pi

第一章:入门

2024.8.3

  • for 循环几种写法
  • -
  • range 关键字
  • 变量的定义

2024.8.5

:= 语言规则

  1. := 必须在函数体内使用。
  2. 简短声明变量的语句。将声明变量与变量赋值合并。 x:=2
  3. 多变量定义。 x,y,z := 1,2,3
  4. 类型推断。 name := "wangzhy"
  5. 注意,在使用 := 时必须至少有一个新变量。
func main(){
x := 5
x,y := x+2, x*2
fmt.Println(x,y)
}

make(map[string]int) 语法

  1. map[string]int
  • map go 内置数据结构
  • string map 的 key 的类型
  • int map 的 value 的类型

map[string]int 表示一个 key 为 string 类型,value 为 int 类型的 map。

  1. make 语法

make 返回一个已经分配内存的引用。

input := bufio.NewScanner(os.Stdin)

  • bufio: go 的标准库包,提供 I/O 功能。
  • NewScanner: 创建一个新的 Scanner
  • Scanner: 逐行输入。
  • os: go 标准包,提供操作系统相关的功能。
  • os.Stdin: io.Reader 类型,标准的输入流。

运行 go

  • 直接运行 go 文件
go run xxx.go [param1, param2 ...]
  • 先编译,后运行
go build xxx.go
./xxx param1 param2 ...

2024.8.19

  • 命名

    • 大写开头: 可以被外部的包访问。 fmt.Printf
    • 小写开头: 包内部访问。
  • 声明

    • var 变量
    • const 常量
    • type 类型
    • func 函数
  • 指针

    • p &p *p
  • 问题

    • 执行了 fmt.Printf 方法时,会输出%!(EXTRA float64=100)%。 原因: 使用了 %d、%g 占位符,但是传递的参数类型不匹配。
    • %d:匹配 int 类型,%g:匹配 float 类型。

2024.9.22

  • 变量
    • var 名称 类型 = 表达式
    • var s string
    • var i,j,k int
    • var b,f,s = true,2.3 ,"four"
    • var f,err = os.Open(name)
  • 简短变量生命
    • t:=0.0
    • i,j := 0,1
    • i,j := j,i 交换 i 和 j 的值
  • 指针
    • 一个指针的值是另一个变量的地址。
    • 一个指针对应变量在内存中的存储位置。
    • var x int &x *int
x:=1
p := &x
*p = 2
var x,y int
&x == &x // true
&x == &y // false
&x == nil // false
var p = f()
func f() *int{
v :=1
return &v
}

f() == f() // false
func incr(p *int) int{
*p++
return *p
}
v := 1
incr(&v) // v = 2
fmt.Println(incr(&v)) // v = 3
  • new 函数
    • p := new(int)
    • *p = 2
  • 变量的生命周期
    • 包一级别:和整个程序的运行周期是一致的。
    • 局部变量:从创建变量到该变量不再被引用。
  • 赋值
    • x = 1
    • *p = true
    • person.name = "bob"
    • count[x] = count[x] * scale count[x] *= scale
  • 元组赋值
    • x,y = y,x
func gcd(x,y int) int{
for y != 0 {
x,y = y,x%y
}
return x
}
func fjb(n int)int{
x,y := 0,1
for i := 0; i<n;i++ {
x,y = y,x+y
}
return x
}
  • 可赋值性

    • medals := []string{"gold","silver","bronze"}
  • 类型

    • 变量、表达式
    • type 类型名字 底层类型
  • 包和文件

  • 作用域

func f() {} 
var g = "g"
func main(){
f := "f"
fmt.Println(f) // "f"; local var f shadows package-level func f
fmt.Println(g) // "g"; package-level var
fmt.Println(h) // compile error: undefined: h
}
func main(){
x := "hello" // 定义第一个 x 变量
for i:=0; i<len(x); i++{
x := x[i] // 定义第二个 x 变量
if x != '!'{
x := x + 'A' - 'a' //定义第三个 x 变量
fmt.Printf("%c",x) // 输出第三个 x 变量的值
}
}
}
if x:= f(); x == 0 {  // 声明 x 变量
fmt.Println(x)
} else if y := g(x); x == y { // 在这里可以使用 x 变量
fmt.Println(x,y)
} else {
fmt.Println(x,y) // 这里可以使用 x,y 变量
}
// fmt.Println(x,y) // compile error

错误代码

if f,err := os.Open(fname); err != nil {
return err
}

f.ReadByte() // compile error: f 是在 if 条件里面创建的,在此不能使用。
f.Close()

推荐

f,err := os.Open(fname)
if err != nil {
return err
}
f.ReadByte()
f.Close()

不推荐

if f, err := os.Open(fname); err != nil {
return err
} else {
f.ReadByte()
f.Close()
}

基础数据类型

  • 数字
    • 整形
      • int8
      • int16
      • int32
      • int64
      • uint8
      • uint16
      • uint32
      • uint64
      • int
      • uint
      • uintptr
    • 浮点数
      • float32
      • float64
    • 复数
      • complex64
      • complex128
  • 布尔
    • true
    • false
  • 字符串
    • 不可变的字节序列
    • Unicode
    • UTF-8
    • 字符串和 Byte 切片
      • bytes
      • strings
        • 查询
        • 替换
        • 比较
        • 截断
        • 拆分
        • 合并
      • strconv
      • unicode
    • 字符串和数字的转换
    • 常量
      • const pi = 3.1415926

复合数据类型

  • 数组
    • var a [3]int
    • var q [3]int = [3]int{1,2,3}
    • q := [...]int{1,2,3}
    • r := [...]int{99:-1} // 定义了一个含有100个元素的数组r,最后一个元素被初始化为-1,其它元素都是用0初始化。
  • slice
    • 变长的序列,每个元素类型相同。
    • []T
    • 指针、长度、容量
    • months := [...]string{1: "January", /* ... */, 12: "December"}
    • s[i:j],其中0 ≤ i≤ j≤ cap(s),用于创建一个新的slice,引用s的从第i个元素开始到第j-1个元素的子序列。
    • slice 之间不能比较。(slice 可以与 nil 进行比较)
    • slice 判空 len(s) == 0
    • make([]T,len)
    • make([]T,len,cap)
    • append 函数
  • map
    • 是一个无序的key/value对的集合
    • map[K]V
    • map中所有的key都有相同的类型,所有的value也有着相同的类型,但是key和value之间可以是不同的数据类型。
    • ages := make(map[string]int) // mapping from strings to ints
    • map[string]int{}
    • Go语言中并没有提供一个set类型
  • 结构体
    • 结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体。
  • JSON
  • 文本和HTML模板

引用类型

  • 指针
  • 切片
  • 字段
  • 函数
  • 通道

2024.12.03

range 关键字用法

  1. 遍历数组和切片
numbers := []int{10,20,30}
for index,value := range numbers{
fmt.Printf("Index: %d, Value: %d \n",index,value)
}
  1. 遍历数组
  2. 遍历字符串
  3. 遍历通道 channel
  4. 仅需要键或值

rune 的用法

rune 是一种数据类型,表示一个 unicode 字符,实际上是 int32 的别名。

数组与 slice 的区别

数组:定长 slice: 变长

2024.12.04

go mod

版本管理

go mod download

指针本质上也是一个变量,保存的是另一个变量的内存地址.

指针的作用:

  1. 让函数修改我们传入变量的值

2024.12.24

变量声明

var name string
var (
a string
b int
c bool
d float32
)

var name string = "wangzhy"
var fullName , age = "wangzhiyuan", 18

// 类型推导
var firstName = "wang"
var realAge = 27

// 简短变量声明 必须在函数内部
lastName :="zhiyuan"