《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
测试一个数是不是 NaNmath.Pi
第一章:入门
2024.8.3
for
循环几种写法-
range
关键字- 变量的定义
2024.8.5
:=
语言规则
:=
必须在函数体内使用。- 简短声明变量的语句。将声明变量与变量赋值合并。
x:=2
- 多变量定义。
x,y,z := 1,2,3
- 类型推断。
name := "wangzhy"
- 注意,在使用
:=
时必须至少有一个新变量。
func main(){
x := 5
x,y := x+2, x*2
fmt.Println(x,y)
}
make(map[string]int)
语法
map[string]int
map
go 内置数据结构string
map 的key
的类型int
map 的value
的类型
map[string]int
表示一个 key 为 string 类型,value 为 int 类型的 map。
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 类型。
- 执行了 fmt.Printf 方法时,会输出
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
关键字用法
- 遍历数组和切片
numbers := []int{10,20,30}
for index,value := range numbers{
fmt.Printf("Index: %d, Value: %d \n",index,value)
}
- 遍历数组
- 遍历字符串
- 遍历通道 channel
- 仅需要键或值
rune
的用法
rune 是一种数据类型,表示一个 unicode 字符,实际上是 int32 的别名。
数组与 slice 的区别
数组:定长 slice: 变长
2024.12.04
go mod
版本管理
go mod download
指针本质上也是一个变量,保存的是另一个变量的内存地址
.
指针的作用:
- 让函数修改我们传入变量的值
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"