Go学习笔记
1. byte与rune 字符串
byte 占用1个字节,8个bit,范围为0->255(uint8)
rune 占用4个字节,32个bit,范围为0-2^32(int32)(字符集大,中文必须使用这个)
func main() {
var a byte = 'A'
var b rune = 'B'
fmt.Printf("a 占用 %d 个字节数\nb 占用 %d 个字节数", unsafe.Sizeof(a), unsafe.Sizeof(b))
}
//1 4
字符串
一个英文字符占1个字节,一个中文字符占3个字节
//表示 \r\n 这个字符串
//解释型表示法
var str string = "\\r\\n"
//原生型表示法(不会根据转义字符解析)
var str string = `\r\n`
//使用%q还原原生型表示法
fmt.Printf("的解释型字符串是: %q", str)
2. go指针
创建方法
- 定义变量取内存地址
a:=1
p=&a
- 创建指针分配内存后,再给指针指向的内存写入值
str:=new(string)
*str="test"
- 声明指针变量,从其他变量取地址并赋值
a:=1
var b *int
b=&a
& 在普通变量中取内存地址
* 该符号在赋值操作符的右边时,表示在指针变量在取得变量值,在左边是,是指指针指向的变量
打印内存地址
fmt.Printf("%p", p)
fmt.Println(p)
指针具有类型,比如string,int,*float64
指针的零值为nil
指针和切片都是引用类型,改变一个数组的值时,有两个方法:
- 传入数组切片(推荐使用)
func modify(nums []int) {
nums[0] = 90
}
func main() {
nums := [3]int{89, 90, 91}
modify(nums[:])
}
- 传入数组指针
func modify(nums *[3]int) {
(*nums)[0] = 90
}
func main() {
nums := [3]int{89, 90, 91}
modify(&nums)
}
3. select用法
func main() {
c1 := make(chan string, 1)
c2 := make(chan string, 1)
timeout := make(chan bool, 1)
go makeTimeout(timeout, 2)
select {
case msg1 := <-c1:
fmt.Println("c1 received: ", msg1)
case msg2 := <-c2:
fmt.Println("c2 received: ", msg2)
case <-timeout:
fmt.Println("Timeout, exit.")
}
}
//一直阻塞,导致超时
- select 只能用于 channel 的操作(写入/读出/关闭),而 switch 则更通用一些;
- select 的 case 是随机的,而 switch 里的 case 是顺序执行;
- select 要注意避免出现死锁,同时也可以自行实现超时机制;
- select 里没有类似 switch 里的 fallthrough 的用法;
- select 不能像 switch 一样接函数或其他表达式。
4. go异常机制
触发panic
panic("crash")
recover(),捕获panic信息并打印
defer func() {
// recover() 可以将捕获到的panic信息打印
if err := recover(); err != nil {
fmt.Println(err)
}
}()
即使 panic 会导致整个程序退出,但在退出前,若有 defer 延迟函数,还是得执行完 defer 。
defer 在多个协程之间是没有效果,在子协程里触发 panic,只能触发自己协程内的 defer,而不能调用 main 协程里的 defer 函数的。
panic:抛出异常,使程序崩溃
recover:捕获异常,恢复程序或做收尾工作
5. 结构体
结构体可以继承
type Person struct {
Name string
}
type Man struct {
person
age string
}
结构体中,属性名大写为Public,小写为Private
实例化方法:
- 正常实例化
p:=Person{name:"xxx"}
- 使用new
p:=new(Person)
p.name="xxx"
- 使用&
var p *Person=&Person{}
p.name="xxx"
//等同于(*p).name="xxx"
从一个结构体实例对象中获取字段的值,通常都是使用 . 这个操作符,该操作符叫做 选择器。
可以直接省去 * 取值的操作,选择器 . 会直接解引用