# Go语言经验总结
# 变量仅声明
// 值类型声明时,默认零值
var i1 int8
var i2 int64
var s string
var b byte
var r rune
var arrInt [3]int
var arrString [3]string
var arrBool [3]bool
1. 函数定义时,参数也是执行声明操作,func (x int)
# 变量初始化
// 字面量 {} 形式,类似Python()
var arrString = [3]string{"linda", "tom", "catherine"}
// 已经存在2个零值的元素了
var a = make([]int, 2, 10)
// 切片为引用类型,赋值或函数传参,会相互影响,copy可以完全复制拷贝
// 使用时得注意 先申请长度len相同的初始值
var d = make([]int, 2)
copy(d, a)
// 引用类型需要make进行申请地址,才能赋值使用
make([]int, 0, 10)
make(map[string]int, 10)
1. 初始化时用到赋值操作符 =
2. 切片 []int 是一种复数类型
# 函数
// 定义函数类型
type Calc func(int, int)int
var c Calc // nil
// 将匿名函数保存到变量
add := func(x, y int) {
fmt.Println(x + y)
}
defer fmt.Println(1)
defer fmt.Println(2)
// recover()必须搭配defer使用
// defer一定要在可能引发panic的语句之前定义
defer func() {
err := recover()
// 如果程序出出现了panic错误,可以通过recover恢复过来
if err != nil {
fmt.Println("recover: ", err)
}
}()
# 结构体
type singleton struct {
Name string
Age int8
}
// 引用类型或指针类型 只做指针变量声明时,为nil,也就是没有对应内存地址
var instance *singleton
fmt.Println(instance, instance == nil) // <nil> true
// 结构体为值类型,只做值变量声明时,为对应零值,不能和nil比较
var inst1 singleton
fmt.Println(inst1)
fmt.Println(&inst1) // 地址肯定不是 nil
// new 可以申请值类型的内存地址,可以和nil比较
var inst2 = new(singleton)
fmt.Println(inst2, inst2 == nil) // &{ 0} false
// 与new作用相同
var inst3 = &singleton{}
fmt.Println(inst3, inst3 == nil) // &{ 0} false
# 读写操作
// 面向接口编程,resp.Body 实习 Reader中Read方法
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("ReadAll Err:", err)
return
}
// Read比较有意思,是向输入参数p中写数据和返回n个数实现的
type Reader interface {
Read(p []byte) (n int, err error)
}
# for循环局部变量
var urls = []string{
"http://www.baidu.com",
"http://www.google.com",
"http://www.bing.com",
}
func main() {
var wg sync.WaitGroup
for _, url := range urls {
url := url // 把for作用域下url变量,拷贝一份,从而url变得不同
wg.Add(1)
go func() {
defer wg.Done()
fmt.Printf("url pointer: %p\n", &url)
}() // 或者把url作为函数参数传到函数中
}
wg.Wait()
}
# 编程习惯
// Go语言习惯定义变量,然后作为参数传到函数里,函数内部修改该变量值,而函数返回值一般有err作为是否正常标志
stu := &Student{}
err := json.Unmarshal([]byte(rawStr), stu)
err := recover()
err != nil{
panic(err)
}
// type 定义类型
// var 声明变量
// struct 组合类型
// v, ok := 组合
v, ok := m["linda"]
v, ok := x.(string)
v, ok := <- ch
# 切片与数组
- 打印数组时,只会打印len长度以内的元素,虽然底层数据可能不止len个元素
- 底层数组是可以被多个slice同时指向的,因此对一个slice的元素进行操作是有可能影响到其他slice
# 并发编程
go hello()
不是自己做,而是与其他人一起做struct
可以看做一个精密的作用域,作用域内自己定义变量和方法,外部使用时声明初始化变量即可
// 互斥锁版
type MutexCounter struct {
counter int64
lock sync.Mutex
}
func (m *MutexCounter) Inc() {
m.lock.Lock()
defer m.lock.Unlock()
m.counter++
}
func (m *MutexCounter) Load() int64 {
m.lock.Lock()
defer m.lock.Unlock()
return m.counter
}
# 读写操作
// python
for msg in msg_list:
f.write(msg)
for msg := range ch{
fmt.Fprintln(conn, msg)
}