杂记
- 只有两种声明方式:普通声明、初始化声明!
interface{}
变量表示任意类型的值!- 将切片中的数据变成一个个独立的数据:
切片...
sync.Mutex
:互斥锁,不是可重入锁! 当上次Lock()
后没有被Unlock()
,下次的Lock()
会因为锁被其他go占用而阻塞!log.Fatal(err)
会控制台打印err,且会终止程序!- 结构体定义不需要
,
,而初始化必须每个结尾! - Go没有函数重载!
- 函数中参数:
小内存数据类型适用:非指针+返回值 !【传递速度更快,这也就是math
中函数更喜欢非指针参数】
大内存数据类型适用:指针!【结构体】 - 结构体传递用指针!!!!(1.传递更快 2.保证共用一个结构体)
- 自定义结构体想使用
sort
包中方法,就需要实现sort
包中Interface
接口! 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]
})
map
类型没有清空方法,清空是直接创建一个新值!【并行垃圾回收效率很高】new
和make
是专门做内存分配的- 不只是结构体,只要是type都可以:
// An IntHeap is a min-heap of ints.
type IntHeap []int
func (h *IntHeap) Push(x interface{}) {
...
}
- 直隶属同一个文件夹中的数据都是通的,相当于在一个文件中!
g.Add(1)
和g.Wait()
必须是同一个goroutine!sync.WaitGroup
:基于CAS- 只有
struct
类型有语法糖(将ins.Id
转换为了(*ins).Id
),而其他类型(接口啊…)都没有这种语法糖! - 除过main goroutine,其他go结束 其创建的子go并不会立即结束,而会继续运行!
- os的文件File,sql的Rows必须
Close()
! - 结构体的属性必须对外开放(首字母大写)才能被json包
Marshal(v interface{})
序列化! - main包不向外部提供任何参数与方法!只是程序入口包!(因为其他包不能import main包,不然必然造成循环引用)
- 读取器要有截至标志:
reader.ReadString('\n')
; 写入器要有:writer.Flush()
! - 字符串等基本类型传值直接是数值,而字符串只是复制了数据地址和对应长度,而不会复制底层的数组结构。(类似切片) 但由于字符串是不可变的,如果修改或重写赋值,则会重新创建!!!
- 注意:闭包(使用外部变量的匿名函数),并不会拷贝外部变量,会直接修改外部变量的值! 所以它才表现出记忆能力!
- copy、sort等都是面向切片的,甚少使用数组。
- 可变参数是切片!
- CPU缓存命中率!
- Go语言中的指针值是动态变化的:Go语言会给goroutine动态分配栈!==> 栈扩容就需要数据拷贝 ==> 数据的地址就会发生变化 ==> Go语言会刷新所有的地址!(所以Go语言中不能将一个地址的值保存到变量中!!!)
- 方法 面向类型!
- 注意: 结构体在创建时常使用指针!但在继承中,内部的匿名结构体(父类)必须是对象类型!【继承的是类型啊,不是指针啊!】
type TCPConn struct {
conn
}
- Go的继承没有多态,但是接口有多态!
- Goroutine采用半抢占式协作调度,只有当前Goroutine发生阻塞时才会导致调度;这个调度是用户进程直接调度的,所以调度发生在用户态;而且Goroutine有共享线程内存,Goroutine切换只需要少量的数据存入寄存器,这比线程切换代价小很多!
- 同样
i++
,不是线程安全的,所以提供了sync/atomic
包! 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
}
- 同样,Go编译器或CPU都会进行指令重排序!(会在保证语义不变的情况下)
import "C"
:引入CGO,可以嵌套C语言!- RPC:远程进程控制(
net/rpc
有时候要学习) - 当API数量超过10个,不建议使用http中的默认路由,而是开源
httprouter
路由!(动态检索树) - 常量是不会给我们设默认值的,必须手动赋值! (如果不赋值,consts中则会继承上一个const的值!)
- 连接redis:官方方案
- 传输层操作属于内核层,我们只是调用tcp的API:
- 字符型默认推导为
rune
(int32) expvar
:对公共变量的进行暴露调试(Goland可以替代 没什么用)- if they are nil, len(v) is zero.
interface{}
可以接受任意类型参数,包括指针。但是*interface{}
就只能接受指针类型map
的key和value存储结构体必须是指针,不然不能修改结构体中的值!- 为
nil
的声明:只有五大引用类型和指针可能为nil
! (切片、map、channel、接口、函数(+指针)的var
声明为nil
) - 注意结构体不会为
nil
:
var once sync.Once
type manager struct {name string}
var single *manager!
func Singleton() *manager{
once.Do(func() {
single = &manager{"a"}
})
return single
}
- 只有切片、map、channel三种特殊类型,用make函数实例化成地址集合!
- Linux后台执行命令
fmt.Fprintln(w *io.Writer,a ...interface{})
- channel特性:
v <- channel
:关闭时会一直返回默认零值
v,ok <- channel
:ok
会检验是否关闭
最好使用forr
:关闭时跳出循环
for d := range ch2 {
...
}
-
只是接口名和结构体指针之间是多态情况!
也就是:&Chinese{}
可以直接转换为Human
!!!
-
字符串格式化常常使用
fmt
:Sprintf(format string, a ...interface{}) string
、Fprintf(w io.Writer, format string, a ...interface{})
-
设置一个结构体标准输出:实现fmt中的Stringer接口,实际就是实现
String() string
方法! -
新的
panic()
会将旧的panic()
覆盖掉! 所以recover()
只能抓一次,且只能抓住的最近的一次panic()
,且不会报错!
func main() { /输出:0
defer func() {
fmt.Println(recover())
}()
defer panic(0)
defer panic(1)
defer panic(2)
}
- 返回值可以不全取,但一定是从左到右返回的:
s := []string{"a","b","c","d"}
for v := range s {
fmt.Println(v)
}
0 1 2 3
- 切片使用make比较特殊,必须要声明长度:
s := make([]int,0)
- 给字符串创建一个读取器:
strings.NewReader("abcd")
- encoding包下是对不同编码数据的操作(
json
xml
binary
csv
…) string
map
channel
都是forr
遍历啊!- 对基本数据类型的操作都是内建函数!
- Go只有UTF-8编码方式
- io缓冲用bufio,内存中数据缓冲:
bytes.Buffer
、strings.Builder
- 语句块:就是一个单独的花括号写代码
{coding}
,特点:相等于一个作用域,可以访问外部变量,外部不能访问内部定义的变量! - 文件名:
chech_login
,方法名:chechLogin
- struct名与属性名首字母都大些,不然json、gorm可能解析不了。
:=
左边变量无论存在否都会新建!
var i int
for i,v := range nums { #此i为新建 并不会改变外部i
......
}
.....
for ... range ...
每次循环返回的值会引用同一个内存地址(因为他每次都是copy出切片…等中的值的)==
是什么就比较什么,指针就比较地址,结构体就比较结构体。- Golang的位运算:https://blog.csdn.net/raoxiaoya/article/details/108995971
s,ok := str.(string)
断言不接收会引发panic!!!- 可以使用
a.(string)
将a断言为string类型,Go的switch又有一种特殊用法:【a.(type)
】
switch v.(type) {
case string:
。。。
case map[string]interface{}:
。。。
}
nil
:向未实例化的channel中发送或获取数据时会永久阻塞
close
:向关闭了的channel中发送数据会panic
,接收数据会返回默认值,false := <- c
- 注意:
默认值,ok := <- c
不会阻塞,要想接受通道数据时阻塞,使用for range
或select case