Go语言杂记

"本文介绍了Go语言的变量声明、切片操作、互斥锁、错误处理、结构体与接口、内存管理、并发与调度、多态性、位运算、数据类型与传递、方法与继承、垃圾回收、编码与I/O。涵盖了Go语言的重要知识点和实践技巧。"
摘要由CSDN通过智能技术生成

杂记

  1. 只有两种声明方式:普通声明、初始化声明!
  2. interface{} 变量表示任意类型的值!
  3. 将切片中的数据变成一个个独立的数据:切片...
  4. sync.Mutex :互斥锁,不是可重入锁! 当上次Lock()后没有被Unlock(),下次的Lock()会因为锁被其他go占用而阻塞
  5. log.Fatal(err) 会控制台打印err,且会终止程序
  6. 结构体定义不需要,而初始化必须每个结尾!
  7. Go没有函数重载!
  8. 函数中参数:
    小内存数据类型适用:非指针+返回值 !【传递速度更快,这也就是math中函数更喜欢非指针参数】
    大内存数据类型适用:指针!【结构体】
  9. 结构体传递用指针!!!!(1.传递更快 2.保证共用一个结构体)
  10. 自定义结构体想使用 sort包中方法,就需要实现sort包中Interface接口!
  11. sort.Slice自定义切片排序方式:【注意:s[i]
	s := []int{1,3,5,6,8,2,5,9}
	sort.Slice(s, func(i, j int) bool {
		return s[i]>s[j]
	})
  1. map 类型没有清空方法,清空是直接创建一个新值!【并行垃圾回收效率很高】
  2. newmake是专门做内存分配的
  3. 不只是结构体,只要是type都可以:
// An IntHeap is a min-heap of ints.
type IntHeap []int

func (h *IntHeap) Push(x interface{}) {
	...
}
  1. 直隶属同一个文件夹中的数据都是通的,相当于在一个文件中!
  2. g.Add(1)g.Wait()必须是同一个goroutine!
  3. sync.WaitGroup:基于CAS
  4. 只有struct类型有语法糖(将 ins.Id转换为了(*ins).Id),而其他类型(接口啊…)都没有这种语法糖!
  5. 除过main goroutine,其他go结束 其创建的子go并不会立即结束,而会继续运行!
  6. os的文件File,sql的Rows必须Close() !
  7. 结构体的属性必须对外开放(首字母大写)才能被json包Marshal(v interface{})序列化!
  8. main包不向外部提供任何参数与方法!只是程序入口包!(因为其他包不能import main包,不然必然造成循环引用)
  9. 读取器要有截至标志:reader.ReadString('\n') ; 写入器要有:writer.Flush()!
  10. 字符串等基本类型传值直接是数值,而字符串只是复制了数据地址和对应长度,而不会复制底层的数组结构。(类似切片) 但由于字符串是不可变的,如果修改或重写赋值,则会重新创建!!!
  11. 注意:闭包(使用外部变量的匿名函数),并不会拷贝外部变量,会直接修改外部变量的值! 所以它才表现出记忆能力!
  12. copy、sort等都是面向切片的,甚少使用数组。
  13. 可变参数是切片!
  14. CPU缓存命中率!
  15. Go语言中的指针值是动态变化的:Go语言会给goroutine动态分配栈!==> 栈扩容就需要数据拷贝 ==> 数据的地址就会发生变化 ==> Go语言会刷新所有的地址!(所以Go语言中不能将一个地址的值保存到变量中!!!)
  16. 方法 面向类型!
  17. 注意: 结构体在创建时常使用指针!但在继承中,内部的匿名结构体(父类)必须是对象类型!【继承的是类型啊,不是指针啊!】
	type TCPConn struct {
		conn
	}
  1. Go的继承没有多态,但是接口有多态!
  2. Goroutine采用半抢占式协作调度,只有当前Goroutine发生阻塞时才会导致调度;这个调度是用户进程直接调度的,所以调度发生在用户态;而且Goroutine有共享线程内存,Goroutine切换只需要少量的数据存入寄存器,这比线程切换代价小很多!
  3. 同样 i++ ,不是线程安全的,所以提供了sync/atomic包!
  4. atomic.Value可以原子操作自定义类型:(回忆:非基本数据类型的结构转换:t,ok := i.(T)
	h := new(Host)

	var av atomic.Value

	av.Store(h)
	hh := av.Load()

	if t,ok := hh.(*Host);ok {
		h = t
	}
  1. 同样,Go编译器或CPU都会进行指令重排序!(会在保证语义不变的情况下)
  2. import "C":引入CGO,可以嵌套C语言!
  3. RPC:远程进程控制(net/rpc 有时候要学习)
  4. 当API数量超过10个,不建议使用http中的默认路由,而是开源httprouter路由!(动态检索树)
  5. 常量是不会给我们设默认值的,必须手动赋值! (如果不赋值,consts中则会继承上一个const的值!)
  6. 连接redis:官方方案
  7. 传输层操作属于内核层,我们只是调用tcp的API:
    在这里插入图片描述
  8. 字符型默认推导为rune(int32)
  9. expvar :对公共变量的进行暴露调试(Goland可以替代 没什么用)
  10. if they are nil, len(v) is zero.
  11. interface{}可以接受任意类型参数,包括指针。但是*interface{} 就只能接受指针类型
  12. map的key和value存储结构体必须是指针,不然不能修改结构体中的值!
  13. nil的声明只有五大引用类型和指针可能为nil (切片、map、channel、接口、函数(+指针)的var声明为nil
  14. 注意结构体不会为nil:
var once sync.Once
 
type manager struct {name string}
var single *manager!

 
func Singleton() *manager{
	once.Do(func() {
		single = &manager{"a"}
	})
	return single
}
  1. 只有切片、map、channel三种特殊类型,用make函数实例化成地址集合!
  2. Linux后台执行命令
    在这里插入图片描述
  3. fmt.Fprintln(w *io.Writer,a ...interface{})
  4. channel特性:
    v <- channel关闭时会一直返回默认零值
    v,ok <- channelok会检验是否关闭
    最好使用forr:关闭时跳出循环
	for d := range ch2 {
		...
	}
  1. 只是接口名和结构体指针之间是多态情况!
    也就是:&Chinese{} 可以直接转换为 Human !!!
    在这里插入图片描述

  2. 字符串格式化常常使用fmt Sprintf(format string, a ...interface{}) stringFprintf(w io.Writer, format string, a ...interface{})

  3. 设置一个结构体标准输出:实现fmt中的Stringer接口,实际就是实现String() string方法!

  4. 新的panic()会将旧的panic()覆盖掉! 所以recover()只能抓一次,且只能抓住的最近的一次panic(),且不会报错!

func main() { /输出:0
	defer func() {
		fmt.Println(recover())
	}()

	defer panic(0)

	defer panic(1)

	defer panic(2)
}
  1. 返回值可以不全取,但一定是从左到右返回的:
	s := []string{"a","b","c","d"}
	for v := range s {
		fmt.Println(v)
	}
	0 1 2 3
  1. 切片使用make比较特殊,必须要声明长度:s := make([]int,0)
  2. 给字符串创建一个读取器:strings.NewReader("abcd")
  3. encoding包下是对不同编码数据的操作json xml binary csv…)
  4. string map channel 都是 forr 遍历啊!
  5. 对基本数据类型的操作都是内建函数!
  6. Go只有UTF-8编码方式
  7. io缓冲用bufio,内存中数据缓冲:bytes.Bufferstrings.Builder
  8. 语句块:就是一个单独的花括号写代码{coding},特点:相等于一个作用域,可以访问外部变量,外部不能访问内部定义的变量!
  9. 文件名:chech_login,方法名:chechLogin
  10. struct名与属性名首字母都大些,不然json、gorm可能解析不了。
  11. := 左边变量无论存在否都会新建!
var i int
for i,v := range nums { #此i为新建 并不会改变外部i
	......
}
.....
  1. for ... range ... 每次循环返回的值会引用同一个内存地址(因为他每次都是copy出切片…等中的值的)
  2. == 是什么就比较什么,指针就比较地址,结构体就比较结构体。
  3. Golang的位运算:https://blog.csdn.net/raoxiaoya/article/details/108995971
  4. s,ok := str.(string)断言不接收会引发panic!!!
  5. 可以使用a.(string)将a断言为string类型,Go的switch又有一种特殊用法:【a.(type)
switch v.(type) {
	case string:
			。。。
	case map[string]interface{}:
			。。。
		}
  1. nil:向未实例化的channel中发送或获取数据时会永久阻塞
    close:向关闭了的channel中发送数据会panic,接收数据会返回默认值,false := <- c
  2. 注意:默认值,ok := <- c不会阻塞,要想接受通道数据时阻塞,使用for rangeselect case
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值