go经典知识及总结
1.无论sync.Mutex还是其衍生品都会提示不能复制,但是能够编译运行
加锁后复制变量,会将锁的状态也复制,所以 mu1 其实是已经加锁状态,再加锁会死锁.
所以此题的答案是 fatal error;
type MyMutex struct {
count int
sync.Mutex
}
func main() {
var mu MyMutex
mu.Lock()
var mu1 = mu
mu.count++
mu.Unlock()
mu1.Lock()
mu1.count++
mu1.Unlock()
fmt.Println(mu.count, mu1.count)
}
2.defer对于有返回变量的函数,它的生命其可以保留到return之后.
func main() {
fmt.Println(doubleScore(0)) //0
fmt.Println(doubleScore(20.0)) //40
fmt.Println(doubleScore(50.0)) //100
}
func doubleScore(source float32) (score float32) {
defer func() {
if score < 1 || score >= 100 {
score = source //最终还能修改返回值
}
}()
return source * 2
}
3.sync.Mutex不能重复加锁
var mu sync.Mutex
var chain string
func main() {
chain = "main"
A()
fmt.Println(chain)
}
func A() {
mu.Lock()
defer mu.Unlock()
chain = chain + " --> A"
B()
}
func B() {
chain = chain + " --> B"
C()
}
func C() {
mu.Lock() //A处还没有UnLock,此处又加锁,所以出现deadlock
defer mu.Unlock()
chain = chain + " --> C"
}
3.go的for语句几大特别之处
a.break到指定的层级
func main() {
OuterLoop:
for i := 0; i < 2; i++ {
InLoop:
for j := 0; j < 5; j++ {
switch j {
case 2:
fmt.Println(i, j)
break InLoop
case 3:
fmt.Println(i, j)
break OuterLoop
}
}
}
}
b.类似于while
for true{
//do sth.
}
for{
//do sth.
}
c.三分号的用法和c++类似
for ; step > 0; step-- {
fmt.Println(step)
}
for ; ; i++ {
if i > 10 {
break
}
}
func main() {
v := []int{1, 2, 3}
for i, n := 0, len(v); i < n; i++ {
v = append(v, i)
}
fmt.Println(v)
}
4.go的一些预定义字符
这些不是关键字,但最好不要拿去用,面试出这样的题的话,意义不大,只能拿来搞怪.
true /false
append 函数
append 函数用于向切片中添加元素,并返回新的切片。
make 函数
make 函数用于创建切片、映射和通道。
new 函数
new 函数用于分配内存并返回指向新分配的零值对象的指针。
len 函数
len 函数用于返回字符串、切片、映射、通道、数组等的长度。
cap 函数
cap 函数用于返回切片、数组、通道等的容量。
copy 函数
copy 函数用于复制切片中的元素。
delete 函数
delete 函数用于从映射中删除指定的键值对。
print 和 println 函数
print 和 println 函数用于打印输出信息。
panic 和 recover 函数
panic 函数用于引发运行时错误,recover 函数用于捕获并处理运行时错误。
close 函数
close 函数用于关闭通道。
5.有参返回类型可以直接return
以下等价,但是return的作用域内(代码块内)必须有ret变量的存在,
下图中ret被新的ret隐藏了,导致return所在作用域丢失ret.所以无法编译.
func add1(a, b int) (ret int) {
ret = a + b
return
}
func add2(a, b int) (ret int) {
ret = a + b
return ret
}
6.json.Unmarshal必须传入目标指针
虽然map的根本就是hmap指针,但是 reflect.ValueOf(v).Kind()获取到的不是指针,所以也必须传入指针.
func (d *decodeState) unmarshal(v any) error {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Pointer || rv.IsNil() {//!!
return &InvalidUnmarshalError{reflect.TypeOf(v)}
}
d.scan.reset()
d.scanWhile(scanSkipSpace).
err := d.value(rv)
if err != nil {
return d.addErrorContext(err)
}
return d.savedError
}
7.slice因为切片底层公用数组,容易导致数据共享和不能内存不能及时释放
func get() []byte {
raw := make([]byte, 10000)
fmt.Println(len(raw), cap(raw), &raw[0])
return raw[:3]
}
func main() {
data := get()
fmt.Println(len(data), cap(data), &data[0])
}
8.go 语言中的可比较类型和不可比较类型
注意不可比较类型就三个:map slice func,可nil类型还包括chan,指针
但是chan,指针可以用于等值比较
操作符 | 变量类型 |
---|---|
等值操作符 (==、!=) | 整型、浮点型、字符串、布尔型、复数、 指针、管道、接口、结构体、数组 |
排序操作符 (<、<=、> 、 >=) | 整型、浮点型、字符串 |
不可比较类型 | map、slice、function |
所以下面代码结果为false,同一类型指针是可以进行相等比较的
type foo struct{ Val int }
type bar struct{ Val int }
func main() {
a := &foo{Val: 5}
b := &foo{Val: 5}
fmt.Print(a == b)
}
9.go每个case上的表达式都会执行,但只有一个chan可以读取或设置值
https://xie.infoq.cn/article/49526fb0dde758d663dfe0cd0 完整地介绍chan使用
func A() int {
fmt.Println("A", GoID())
time.Sleep(500 * time.Millisecond)
return 1
}
func B() int {
fmt.Println("B", GoID())
time.Sleep(1000 * time.Millisecond)
return 2
}
func GoID() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
func main() {
ch := make(chan int, 1)
go func() {
select {
case ch <- A():
{
fmt.Println("caseA")
}
case ch <- B():
{
fmt.Println("caseB")
}
default:
ch <- 3
}
}()
for v := range ch {
fmt.Println(v)
}
}
10.基础类型的map可以++,非基础类型不行.
这种差异造成诡异的心智负担.
func main() {
m := make(map[string]int)
m["foo"]++ //基础类型没有问题
fmt.Println(m["foo"])
m2 := map[string]Person{}
m2["foo"] = Person{1}
m2["foo"].Age = 22 //非法操作
}
type Person struct {
Age int
}
11.一个接口是否==nil,要看其类型和数值是否同时为nil
打印则看数值
func Foo() error {
var err *os.PathError = nil
return err
}
func main() {
err := Foo()
fmt.Println(err) //nil,打印则看数值
fmt.Println(err == nil) //false
}
func main() {
x := interface{}(nil)
y := (*int)(nil)
a := y == x //类型不一样
b := y == nil //y不是接口,所以直接看值.如果var y any = (*int)(nil)就变成接口了.最后接口就是false.
_, c := x.(interface{}) //没有类型,断言失败
println(a, b, c) //flase true false
}
12.在go里面0开始的数字是八进制
const (
Decade = 010
)
func main() {
fmt.Println(Decade) //8
}
13.字符串Trim操作注意
Trim结尾处的字符串,对应其他语言的TrimEnd
TrimSuffix
切勿使用TrimRight,会将第二个参数字符串里面所有的字符拿出来处理,只要与其中任何一个字符相等,便会将其删除
fmt.Println(strings.TrimRight("ABBA", "BA")) //最后全部被删了
Trim以某段开始的字符串,对应其他语言的TrimStart
TrimPrefix
fmt.Println(strings.TrimLeft("ABBAC", "BA")) //最后只会剩下C
14.关于for range
如果是chan则,没有k,只有v;
for v := range ch {
fmt.Println(v)
}
15.关于切片两个冒号的说明
https://segmentfault.com/a/1190000018356577
注意
我们潜意识觉得cap就是底层数组的长度,但是在尽显冒号切片时,cap的长度是有max-low得到的,max的默认值为源切片(或源数组)的cap.
通过两个冒号创建切片,slice[x:y:z]切片实体[x:y]切片长度len = y-x,切片容量cap = z-x\
data := [...]int{0, 1, 2, 3, 4, 5, 6} //初始化一个数组
slice := data[1:4:5] // [low : high : max] 通过两个冒号创建切片
使用两个冒号[1:4:5] 从数组中创建切片,长度为4-1=3,也就是索引从1到3 的数据(1,2,3)
然后,后面是最大是5,即容量是5-1=4,即,创建的切片是长度为从索引为 1、2、3 的切片,底层数组为[ 1,2,3,4]
data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
data[:6:8] [0 1 2 3 4 5] //默认low为0
data[5:] [5 6 7 8 9] //省略 high、 max,默认值为源切片(或源数组)的cap
data[:3] [0 1 2] //low=0,max=默认值为源切片(或源数组)的cap
data[:] [0 1 2 3 4 5 6 7 8 9] //10 10 全部省略。
一道题懂了,那真懂了.
func main() {
a := []int{0, 1, 2, 3}
s := a[1:3] //1,2,[3]
s2 := s[1:2] //2,[3]
fmt.Println(cap(s), len(s))
fmt.Println(cap(s2), len(s2))
fmt.Println("--------------------------------")
s2 = append(s2, 333)
fmt.Println(a)
fmt.Println(s)
fmt.Println(s2)
}
3 2
2 1
--------------------------------
[0 1 2 333]
[1 2]
[2 333]
16.关于切片的一些手法
创建空切片
// 使用 make 创建空的整型切片
slice := make([]int, 0)
// 使用切片字面量创建空的整型切片
slice := []int{}
17.for range 常数
for i := range 10 {
fmt.Println(i)
}
18.关于一切等值运算的根本是比较补码
func main() {
count := 0
for i := range [256]struct{}{} {
m, n := byte(i), int8(i)
if n == -n {
count++
fmt.Println("n==-n", n, -n, i)
}
if m == -m {
count++
fmt.Println("m==-m", m, -m, i)
}
}
fmt.Println(count)
}
n==-n 0 0 0
m==-m 0 0 0
n==-n -128 -128 128
m==-m 128 128 128
4
-128 的补码:
首先,我们需要知道 -128 的原码。原码是表示数值的二进制形式,其中最高位表示符号位(0 表示正数,1 表示负数),其余位表示数值部分。对于 -128,其原码为 1000 0000。
接下来,我们求出 -128 的反码。反码是将原码的除符号位外的各位取反。对于 -128,其反码为 1111 1111。
最后,我们计算 -128 的补码。补码是在反码的末位加1,从而使后7位再次发生溢出,进位丢弃,符号位不变。因此,-128 的补码为 1000 0000。
需要注意的是,-128 是一个特殊的数,因为它的绝对值比最小的32位整数还要大1,所以在计算机中表示为 -128 的补码时,我们直接使用其反码加1的结果。
128的补码
128 的原码是 10000000。三码都是这个,所以也是 10000000。
19.多重赋值的优先级
多重赋值分为两个步骤,有先后顺序:
- 计算等号左边的索引表达式和取址表达式,接着计算等号右边的表达式;
- 赋值;
func main() {
var a []int = nil
a, a[0] = []int{1, 2}, 9
fmt.Println(a)
}
解析:运行时错误。知识点:多重赋值。
19.sync.WaitGroup不能复制值,且需要在启动协程前Add
func main() {
wg := sync.WaitGroup{}
for i := 0; i < 5; i++ {
go func(wg sync.WaitGroup, i int) {
wg.Add(1)
fmt.Printf("i:%d\n", i)
wg.Done()
}(wg, i)
}
wg.Wait()
fmt.Println("exit")
}
20.chan的基本数据结构
ype hchan struct {
qcount uint // 队列中的总元素个数
dataqsiz uint // 环形队列大小,即可存放元素的个数
buf unsafe.Pointer // 环形队列指针
elemsize uint16 //每个元素的大小
closed uint32 //标识关闭状态
elemtype *_type // 元素类型
sendx uint // 发送索引,元素写入时存放到队列中的位置
recvx uint // 接收索引,元素从队列的该位置读出
recvq waitq // 等待读消息的goroutine队列
sendq waitq // 等待写消息的goroutine队列
lock mutex //互斥锁,chan不允许并发读写
}
21.cap 关于 cap 函数适用下面哪些类型?
A. 数组;
B. channel;
C. map;
D. slice;
func main() {
c := make(chan int, 2)
c <- 11
fmt.Println(len(c)) //1
fmt.Println(cap(c)) //2
}
22.启动一个goroutine的前提是,还有数
func main() {
runtime.GOMAXPROCS(1)
go func() {
for i:=0;i<10 ;i++ {
fmt.Println(i)
}
}()
for {}
}
23.接收器方法在defer时也会优先求值
type Slice []int
func NewSlice() Slice {
return make(Slice, 0)
}
func (s *Slice) Add(elem int) *Slice {
*s = append(*s, elem) //!! 注意无名类型的特别之处.
fmt.Print(elem)
return s
}
func main() {
s := NewSlice()
defer s.Add(1).Add(2)
s.Add(3)
}
//1 3 2
24.闭包引用相同变量,那么他们的作用效果都在这个变量上
func test(x int) (func(), func()) {
return func() {
println(x)
x += 10
}, func() {
println(x)
}
}
func main() {
a, b := test(100)
a()
b()
}
// 100 110
25.range相当于一个函数,会对传入的数据进行拷贝.
因此,下面切片和数组的场景会产生不同的值
type T struct {
n int
}
func main() {
ts := [2]T{}
//ts := make([]T, 2)
for i, t := range ts {
switch i {
case 0:
t.n = 3
ts[1].n = 9 //改变了ts,但t的数据,源头是range产生的拷贝
case 1:
fmt.Print(t.n, " ")
}
}
fmt.Print(ts)
}
// 数组 0 [{0} {9}]
// 切片 9 [{0} {9}]
//--------------
func main() {
var a = []int{1, 2, 3, 4, 5}
var r = make([]int, 0)
for i, v := range a { //这里产生了新的副本,所以下面的添加操作不影响遍历.
if i == 0 {
a = append(a, 6, 7)
}
r = append(r, v)
}
fmt.Println(r)
}
25.关于defer func recover panic
- panic会将恐慌压入一个后进先出的栈里面;
- recover 必须内置于defer func 内才有效;
- recover从panic栈中取值;
func main() {
defer func() {
fmt.Print(recover())
}()
defer func() {
defer func() {
fmt.Print(recover())
}()
panic(1)
}()
defer recover() //这里的recover没有效果,因为没有在defer func内部
panic(2)
}
上面的代码panic依次入站 2 ,1,出栈为1 ,2,所以结果 1 2
func main() {
defer func() {
fmt.Print(recover())
}()
defer func() {
defer fmt.Print(recover()) //首先参数需要求值,所以在当前执行func完毕时要打印2
panic(1) //压入栈中,当前有没有机会了,上级会捕捉到.
}()
defer recover() //这里的recover没有效果,因为没有在defer func内部
panic(2)
}
结果为 2 1
26. 当闭包含有外层变量时,会让外面的变量一直活着
func F(n int) func() int {
return func() int {
n++
return n
}
}
func main() {
f := F(5) //参数为5
defer func() {
fmt.Println(f())
}()
defer fmt.Println(f()) //需要立即求值,所以最后打印6,参数变成为了6
i := f() //参数变成了7,
fmt.Println(i)//打印7
}
//最后结果768
27.关于for,range对枚举器的赋值
func main() {
var k = 9
for k = range []int{} { //没有数据,所以对k的赋值,没能执行
}
fmt.Println(k)
for k = 0; k < 3; k++ {
}
fmt.Println(k) //很明显上面导致k变成了3
for k = range (*[3]int)(nil) { //一个[三个数据的数组]的指针,虽然是nil,但是在go里面这是合法的,最终k变成2
}
fmt.Println(k)
}
28.关于继承的本质问题
type T struct{}
func (*T) foo() {
}
func (T) bar() {
}
type S struct {
*T //注意指针也可以,也即,没有名称只有类型,那么我们就可以通过语法糖的方式,好像调用自己的方法一样调用
}
func main() {
s := S{}
_ = s.foo
s.foo() //这个是没有问题的.虽然就nil,但因为没有发生调用nil,所以没有问题
_ = s.bar // (* s.T).bar,但指针s.T为nil,解引用失败报错
}
//---------------这是可以的
type X struct {}
func (x *X) test() {
println(x)
}
func main() {
var a *X
a.test()//nil,不是null
X{}.test() //这里有问题,右值不可寻址
}
//--------------------------------------
type Father struct{ Name string }
type Monther struct {
Name string
}
func (m Monther) World() {
}
type Child struct {
Father
Monther
}
func (entity Father) Hello() {
}
func (entity Father) World() {
}
func main() {
child := Child{}
child.World() //二义性语法糖就用不了,需要指明Father or Monther的方法
}
//-----------------------
- 匿名字段的本质字段名是
S *S
S S
- 然后调用他们对应的接收器方法。
- 如果T为指针,则全有,不问上面的两种情况了
- 能不能改变原有数据,取决于接收器是不是指针类型
func main() {
var v T
t := &v
fmt.Printf("%p\n", t.S)
t.SPtr(1) //因为t指针类型,所以拥有S,*S的接收器方法
t.SPtr(1)
fmt.Println(t.S.Age)
}
type S struct {
Age int
}
type T struct {
S
}
func (s S) SVal(dd int) {
s.Age = 10
fmt.Printf("%p\n", &s)
}
func (s *S) SPtr(dd int) {
fmt.Printf("%p\n", s)
s.Age = 100
}
func (t T) TVal(dd int) {
}
func (t *T) TPtr(dd int) {
}
func methodSet(arg interface{}) {
argType := reflect.TypeOf(arg)
fmt.Println(argType.NumMethod())
for i := 0; i < argType.NumMethod(); i++ {
m := argType.Method(i)
fmt.Printf("%s: %v\n", m.Name, m.Type)
}
}
//----------
type Fragment interface {
Exec(transInfo *TransInfo) error
}
type GetPodAction struct {
}
func (g GetPodAction) Exec(transInfo *TransInfo) error {
...
return nil
}
指针接收器拥有值接口器的方法
var fragment Fragment = new(GetPodAction)
####29.关于map的怪异之处,面试时尤其注意
func main() {
var m map[int]bool // nil
var a = m[123]
fmt.Println(a)//false,原因很简单,nil不是null,map不仅允许读取没有的key,还允许读取nil的map
}
30.关于切片
- 关于切片之前的理解是有问题的,我们切片的对象是底层真实的数组长度(即:容量)
- low,high,max high默认是slice的长度,max则为容量
func main() {
x := make([]int, 2, 10)
a := x[6:10]
b := x[6:] //x[6:2],所以这里要报错
c := x[2:] //2-2=0,所以最后是空的
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
}
31.不可比较类型 slice map func
func main() {
var x interface{}
var y interface{} = []int{3, 5}
_ = x == x
_ = y == x //注意虽然slice是不可以比较的类型,但是它可以和any nil比较
println("end")
_ = y == y //2 slice是不可以比较的
}
32.对于接收器方法的表达,我们都很陌生
type N int
func (n N) test() {
fmt.Println(n)
}
func main() {
var n N = 10
fmt.Println(n)
n++
//func (N).test()
f1 := N.test
f1(n)
n++
//var f2 func(*N)
f2 := (*N).test
f2(&n)
}
33.读写nil类型的chan都会永远阻塞
func main() {
var ch chan int
select {
case v, ok := <-ch:
println(v, ok)
default:
println("default")
}
}
34.:=操作符不能给结构体字段赋值
type foo struct {
bar int
}
func main() {
var f foo
f.bar, tmp := 1, 2
}
35.go中所有的变量申明了就必须用,但常量除外,常量不能取地址
func main() {
const x = 123
const y = 1.23
fmt.Println(x)
}
36.byte在go中是uint8的别名,他们完全等价
type byte = uint8
func test(x byte) {
fmt.Println(x)
}
func main() {
var a byte = 0x11
var b uint8 = a
var c uint8 = a + b
test(c)
}
37.关于给切片加索引赋值的注意项
- 字面量初始化切片时候,可以指定索引,没有指定索引的元素,其索引=前一个索引+1,
- 空缺的索引的位置,数据就是零值
var x = []int{2: 2, 3, 0: 1}
func main() {
fmt.Println(x) // [1 0 2 3]
}
38.关于select
A. select机制用来处理异步IO问题;//输入输出,要读取或写入chan
B. select机制最大的一条限制就是每个case语句里必须是一个IO操作;
C. golang在语言级别支持select关键字;
39.指针类型的map和slice均不能使用索引
40.chan的写入方负责关闭,不然造成泄露
func main() {
ch := make(chan int, 100)
// A
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
}()
// B
go func() {
for {
a, ok := <-ch
if !ok {
fmt.Println("close")
return
}
fmt.Println("a: ", a)
}
}()
close(ch)
fmt.Println("ok")
time.Sleep(time.Second * 10)
}
41. chan的几个特性
A. 给一个 nil channel 发送数据,造成永远阻塞
B. 从一个 nil channel 接收数据,造成永远阻塞
C. 给一个已经关闭的 channel 发送数据,引起 panic
D. 从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回一个零值
42.类型转换的方式和c系有差异需要注意
B.
type MyInt int
var i int = 1
var j MyInt = (MyInt)i //c系的方式,在go里面是非法的
C.
type MyInt int
var i int = 1
var j MyInt = MyInt(i)//在才是正确的方式.
43.关于for range枚举器,不同版本有不同定义
type Foo struct {
bar string
}
func main() {
s1 := []Foo{
{"A"},
{"B"},
{"C"},
}
s2 := make([]*Foo, len(s1))
for i, value := range s1 {
s2[i] = &value
}
fmt.Println(s1[0], s1[1], s1[2])
fmt.Println(s2[0], s2[1], s2[2])
}
1.22输出:
{A} {B} {C}
&{A} &{B} &{C}
1.22之前
s2 的输出是 &{C} &{C} &{C}
43.关于defer nil方法
func f(n int) (r int) {
defer func() {
r += n
recover() //这里捕捉了nil方法的调用
}()
var f func()
defer f() //f是一个nil,所以没有机会执行下面的方法
f = func() {
fmt.Println("f called")
r += 2
}
return n + 1
}
func main() {
fmt.Println(f(3)) //7
}
https://www.topgoer.cn/docs/gomianshiti/mian28
go经典知识及总结的更多相关文章
- Swift经典知识整理
1 关于Swift Swift 是一种适用于 iOS 和 OS X 应用的全新编程语言,它建立在最好的 C 和 Objective-C 语言之上,并且没有 C 语言的兼容性限制.Swift 采用安全 ...
- Java经典知识复习
1.自增变量 int i = 1; i = i++; int j = i++; int k = i + ++i * i++; 问i.j.k分别等于? 针对这类题目, 1. 赋值操作=,最后计算: ...
- jQuery相关知识总结
1 encodeURIComponent(city)处理js传值乱码问题 2 总体概述 以后项目如果没有特殊情况,一般采用jQuery作为最基础的公共底层库. 另外对于前端的javascript相关的 ...
- 《学习OpenCV3》第14章课后习题
1.在一条含有 N 个点的封闭轮廓中,我们可以通过比较每个点与其它点的距离,找出最外层的点.(这个翻译有问题,而且这个问题是实际问题) a.这样一个算法的复杂度是多少? b.怎样用更快的速度完成这个任 ...
- 比特币运行原理[z]
https://baijiahao.baidu.com/s?id=1581755535769652543&wfr=spider&for=pc 这篇文章主要讲解比特币是什么?它的运行原理 ...
- ML-学习提纲1
http://www.sohu.com/a/130379077_468714 本文用一系列「思维导图」由浅入深的总结了「统计学」领域的基础知识,是对之前系列文章做的一次完整的梳理,也是我至今为止所有与 ...
- [C0] 人工智能大师访谈 by 吴恩达
人工智能大师访谈 by 吴恩达 吴恩达采访 Geoffery Hinton Geoffery Hinton主要观点:要阅读文献,但不要读太多,绝对不要停止编程. Geoffrey Hinton:谢谢你 ...
- Go语言核心36讲(Go语言实战与应用十四)--学习笔记
36 | unicode与字符编码 在开始今天的内容之前,我先来做一个简单的总结. Go 语言经典知识总结 在数据类型方面有: 基于底层数组的切片: 用来传递数据的通道: 作为一等类型的函数: 可实现 ...
- Go语言核心36讲38
到目前为止,我们已经一起陆陆续续地学完了Go语言中那些最重要也最有特色的概念.语法和编程方式.我对于它们非常喜爱,简直可以用如数家珍来形容了. 在开始今天的内容之前,我先来做一个简单的总结. Go语言 ...
- 数据库的有关知识==>>我们的血泪史之经典练习(1-2)
今天给大家说说数据库的有关知识 抒情一下,想在好困,真的,虽然我在这温暖的教室,身边有知心的盆友, ,很高兴还能是学生的一员,我们还年轻,我们也不会想的太多,高高兴兴上学,快快乐乐回家,每天吃的饱饱, ...
随机推荐
- [转帖]Nacos使用2.0.1版本启动出现9848端口错误的解决方式(亲测有效)
目录 一.背景 二.报错如下 三.报错原因 四.解决方式 一.背景 nacos服务端和客户端都是 2.x版本. centos7使用原始安装nacos单机版,没有使用docker安装naocs集群. 二 ...
- [转帖]《Linux性能优化实战》笔记(23)—— 内核线程 CPU 利用率过高,perf 与 火焰图
在排查网络问题时,我们还经常碰到的一个问题,就是内核线程的 CPU 使用率很高.比如,在高并发的场景中,内核线程 ksoftirqd 的 CPU 使用率通常就会比较高.回顾一下前面学过的 CPU 和网 ...
- mysql8 initialize 命令 初学版 lower_case_table_names
1. 今天开发找我跟我说 我安装的mysql 不对. 比较蛋疼. 需要修改一个参数 但是数据库已经初始进去了 重装起来比较麻烦. 硬着头皮搞. 2. 参数的名字为: lower_case_tabl ...
- Redis6.x 在Windows上面编译安装的过程
背景说明 在github上面仅能够找到 redis3.2.100的Windows安装文件 比较新的版本比较难以找到, 同事经常出现这个版本的redis卡死的情况, 所以想尝试进行一下升级. 第一部分下 ...
- docker -- images镜像消失问题排查
1. 问题描叙 安装model-serving组件时,错误日志输出push时对应的tag不存在,导致镜像推送失败 2. 问题排查 # 找到对应镜像,尝试手动推送 docker images|grep ...
- 30岁程序媛求职路复盘:文转码+失业半年+PHP如何涨薪5K!?
这篇文章来自一位群友的分享: 这篇文章写于下班路上,刚刚入职不久,我想再冲刺一下大厂,阳哥建议我坚持总结打卡,可以尝试写写博客. 那我就从这篇开始吧,希望开个好头! 上班的感觉真好 今天是入职的第二周 ...
- vue中keep-alive详细讲解
场景 今天产品跑过来跟我说, 当我在A页面修改数据后,去B页面. 然后返回A页面.希望A页面保留我修改后的数据. 而不是数据又恢复最初的样子了.我心里想,尼玛,又要加班了? 看下面小粒子 数据被被重置 ...
- windwos10任务栏居中
如下操作 新建一个文件夹如图 然后出现这个重右往左一直拖然后拉出来就行了如图 拖不动或者没有的把这个关了-锁定任务栏 文字如何隐藏? 在这个文字旁边右击关闭标题即可 然后锁定任务栏就OK了
- TienChin 渠道管理-添加渠道
在我们平时新建一个全新的 Java 类,这个类需要存放的包不存在,可以使用如下的方式进行创建: 含义就是说,将 ChannelVO 这个类放在 vo 这个包当中,如果存在则不创建,存在就将新建的类放入 ...
- C/C++ 通过Socket 传输结构体
本质上socket无法传输结构体,我们只有将结构体装换为字节数组,或者是字符串格式来传输,到了服务端在强制类型转换一下即可,下面的代码分别提供原生写法与通过boost的实现两种,直接改改,可用于收集目 ...