# 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)
}
上次更新: 1/10/2023, 12:41:52 PM