golang基础学习笔记

golang基础学习

  • golang
    • 1. 认识golang和goland使用
      • 1.1 goland插件
    • 2. 数据类型
      • 2.1 结构体
    • 3. 流程控制
      • if
      • switch
      • select
      • for
      • range
      • Goto、Break、Continue
    • 4. 函数
      • 4.1 匿名函数
      • 4.2 闭包、递归
      • 4.3 延迟调用
        • 什么是defer
        • defer的常见用途
          • 释放已经获取的资源
          • 从panic中恢复
          • 延迟闭包
          • 参数即时求值
          • 延迟调用多个函数
          • 延迟调用对象的方法
          • 并发时释放共享资源锁
          • 延迟释放文件
          • 延迟关闭tcp连接
          • 延迟关闭数据库连接
      • 4.4 异常处理
        • 异常处理思想
        • 自定义异常
        • 详细的异常信息
        • panic
        • panic recover
      • 4.5 单元测试
        • 压力测试
    • 5. 方法
      • 什么是方法
      • 方法与普通函数的区别
      • 匿名字段
      • 方法集
    • 6. 面向对象
      • 接口
        • 什么是接口
        • 实现接口
        • 接口的作用
        • 值接收者和指针接收者实现接口的区别
            • **值接收者**实现接口
            • **指针接收者**实现接口
      • 类型和接口的关系
        • 一个类型实现多个接口
        • 多个类型实现一个接口
      • 接口嵌套
      • 空接口
        • 空接口的应用
          • 使用空接口实现map、slice存储任意类型值
        • 类型断言
      • 关于接口需要注意的
    • 7. 标准库
      • 反射
        • 空接口和反射
        • 结构体与反射

golang

1. 认识golang和goland使用

1.1 goland插件

File -> Settings -> Plugins -> Marketplace

  • Gopher:将进度条变成golang的标志,更好看
  • Rainbow Brackets:多彩括号
  • Go Linter:代码规范
  • CodeGlance:在编辑区右侧生成一个代码缩略区

2. 数据类型

2.1 结构体

如果结构体中字段首字母小写,该字段将无法正常解析。如果需要字段名首字母小写,可以使用tag的方式。

3. 流程控制

if

switch

select

select语句类似于switch语句,但是select会随机执行一个可运行的case,如果没有case可运行,它将阻塞,直到有case可运行

for

range

Goto、Break、Continue

4. 函数

4.1 匿名函数

匿名函数是指不需要定义函数名的一种函数实现方式

func main() {sum := func(a,b int) int {return a+b}fmt.Println(sum(1,2))
}

4.2 闭包、递归

函数b嵌套在函数a内部,函数a返回函数b

当函数a的内部函数b被函数a外的一个变量引用时,就创建了一个闭包。

从此可以看出闭包的作用就是在函数a执行完并返回后,闭包使得垃圾回收机制GC不会回收函数a所占用的资源。

4.3 延迟调用

什么是defer

通过使用defer修饰一个函数,使其在外部函数"返回后"才被执行,即使外部的函数返回的是panic异常。这类函数被称作延迟调用函数

image-20220112205437552

打印结果:先"first"后"later"

  • deferfinally类似,但是两者的不同是finally的作用域在其**异常块中,而defer的作用域限于包围它的那个函数**。

defer的常见用途

释放已经获取的资源
image-20220112205754174

不管NewFromFile函数是否返回了错误,这个延迟函数都将关闭已经打开的文件。

从panic中恢复

如果defer和被触发的**panic**位于同一个goroutine1中,defer能够使程序从panic中恢复,避免整个程序终止。

image-20220112210852073

其中recover()函数可以返回panic()函数的参数,这就使得我们能自行处理panic,同时也可以向panic中传入错误或其他类型来判断引发panic的究竟是哪一个值。

延迟闭包

一个使用了 defer 的延迟调用函数可以是任意类型的函数,因此,当 defer 作用于一个匿名函数的时候,这个函数就能够获取到外围函数体中的变量的最新状态。

image-20220112211216947
参数即时求值

Go 的运行时会在延迟调用函数声明时保存任何传递到延迟调用函数中的参数,而不是当它被运行的时候。

func count(i int) (n int) {defer func(i int) {n = n + i}(i)i = i * 2n = ireturn
}func main(){count(10)
}// 输出结果为:30

在延迟调用函数声明时,就已经保存了传入到延迟调用函数中的i的值,也就是10。所以最后n = 20 + 10。

延迟调用多个函数

如果有多个延迟函数,那么这些延迟调用函数会按照**声明顺序的反序**执行。

func stacked(){defer func(){fmt.Println("last") }()defer func(){fmt.Println("first")}
}func main(){stacked()
}// 输出结果为:
// first
// last
延迟调用对象的方法
  • 没有使用指针作为接收者
type Car struct {model string
}func (c Car) PrintModel() {fmt.Println(c.model)
}func main() {c := Car{model: "DeLorean DMC-12"}defer c.PrintModel()c.model = "Chevrolet Impala"
}// 输出结果:
// DeLorean DMC-12
  • 使用指针作为接收者
type Car struct {model string
}func (c *Car) PrintModel() {fmt.Println(c.model)
}func main() {c := Car{model: "DeLorean DMC-12"}defer c.PrintModel()c.model = "Chevrolet Impala"
}// 输出结果:
// Chevrolet Impala

当外围函数还没有返回的时候,Go 的运行时就会立刻将传递给延迟函数的参数保存起来。

因此,当一个以值作为接收者的方法被 defer 修饰时,接收者会在声明时被拷贝(在这个例子中那就是 Car 对象),此时任何对拷贝的修改都将不可见(例中的 Car.model ),因为,接收者也同时是输入的参数,当使用 defer 修饰时会立刻得出参数的值(也就是 “DeLorean DMC-12” )。

在另一种情况下,当被延迟调用时,接收者为指针对象,此时虽然会产生新的指针变量,但其指向的地址依然与上例中的 “c” 指针的地址相同。因此,任何修改都会完美地作用在同一个对象中。

并发时释放共享资源锁
延迟释放文件
延迟关闭tcp连接
延迟关闭数据库连接

4.4 异常处理

异常处理思想

go语言中没有try catch,因为try catch会消耗更多的资源。

所以go语言主张:

  • 如果一个函数可能出现异常,那么应该把异常作为返回值,没有异常就返回nil
  • 每次调用可能出现异常的函数时,都应该主动进行检查,并做出反应,这个if语句术语叫做卫述语句

所以,异常应该总是掌握在我们自己的手上,保证每次操作产生的影响达到最小,保证程序及时部分地方出现问题,也不会影响整个程序的运行。

及时的处理异常,这样就可以减轻上层处理异常的压力。同时,也不要让未知的异常使你的程序崩溃。

自定义异常

比如,程序有一个功能为除法的函数,除数不能为0,否则程序出现异常,我们就要提前判断除数,如果为0,则返回一个异常。

func divisionInt(a, b int) (int, error) {if b == 0 {return -1, errors.New("除数不能为0")}return a / b, nil
}func main(){a, b := 4, 0res, err := divisionInt(a, b)if err != nil {fmt.Println(err.Error())return}fmt.Println(a, "除以", b, "的结果是 ", res)
}

注意:

  • 创建一个异常errors.New("字符串")
  • 获取异常信息err.Error()

errors.New("字符串")的形式不支持字符串格式化功能,所以可以使用fmt.Errorf()

err = fmt.Errorf("产生了一个%v的异常","除数为0")

详细的异常信息

errors实现了一个error的接口,这个接口里只有一个Error方法且返回一个string

type error interface{Error() string
}

只要结构体实现了这个方法即可,源码的实现方式如下:

type errorString struct {s string
}func (e *errorString) Error() string {return e.s
}// 多一个函数当作构造函数
func New(text string) error {return &errorString{text}
}

所以,我们只要扩充下自定义error的结构体字段就行了。

type FileError struct{Op stringName stringPath string
}func (f *FileError) Error() string{return fmt.Sprintf("路径为%v的文件%v,在 %v 操作时出错",f.Path,f.Name,f.Op)
}func NewFileError(op string,name string,path string) *FileError{return &FileError(Op:op,Name:name,Path:path)
}

调用:

func main(){f := NewFileError("读","README.md","/home/README.md")fmt.Println(f.Error())
}// 输出结果为:
// 路径为/home/README.md的文件README.md,在 读 操作时出错

panic

程序在什么情况下会崩溃呢?

go的类型系统会在编译时捕获很多异常,但是有些异常只能在运行时检查,如**数组访问越界空指针引用**等。这些运行时异常会引起panic异常(程序直接崩溃退出)。然后在退出的时候调用当前goroutine1的defer延迟调用语句。

有时候在程序运行缺少必要的资源的时候应该手动触发宕机,比如**配置文件解析出错依赖某种独有库但该操作系统没有**的时候。

defer fmt.Println("关闭文件句柄")
panic("人工创建的运行时异常")// 输出结果为:
// 关闭文件句柄
// panic:人工创建的运行时异常

panic recover

出现panic以后程序会终止运行,所以我们应该在测试阶段就发现这些问题,然后进行规避,但是如果在程序中产生不可预料的异常(比如在线的web或者rpc服务一般框架层),即使出现问题(一般是遇到不可预料的异常数据)也不应该直接崩溃,应该打印异常日志,关闭资源,跳过异常数据部分,然后继续运行下去,不然线上容易出现大面积血崩。

func divisionIntRecover(a, b int) (ret int, e error) {defer func() {if err := recover(); err != nil {ret = 0e = fmt.Errorf("出现一个错误")}}()return a / b, nil
}func main(){if i, v := divisionIntRecover(4, 0); i != 2 || v != nil {fmt.Println(v.Error())} else {fmt.Printf("a/b=%v\n", i)}if i, v := divisionIntRecover(4, 2); i != 2 || v != nil {fmt.Println(v.Error())} else {fmt.Printf("a/b=%v\n", i)}
}// 输出结果为:
// 出现了一个错误
// a/b=2

注意:

  • 调用panic后,当前函数从调用点直接退出

  • 捕获函数recover只有在延迟调用内直接调用才会终止错误,否则总是返回**nil**。任何未捕获的错误都会沿调用堆栈向外传递。

    1. 无效示例:没有在延迟调用内直接调用

      func test(){defer fmt.Printf("recover:%v\n", recover())panic("test panic")
      }func main(){test()
      }// 输出结果为:
      // recover:<nil>
      // panic: test panic
      
    2. 无效示例:在延迟调用内,但是没有直接调用

      func test(){defer func(){func(){fmt.Printf("recover1:%v\n", recover())}()}()panic("test panic")
      }func main(){test()
      }// 输出结果为:
      // recover1:<nil>
      // panic: test panic
      
    3. 正确示例:在延迟调用内直接调用

      func test(){defer func(){fmt.Printf("recover2:%v\n", recover())}()panic("test panic")
      }func main(){test()
      }// 输出结果为:
      // recover2:test panic
      

4.5 单元测试

测试文件名以_test.go的文件是go test测试的一部分,*_test.go文件中有三个类型的函数:

类型格式作用
测试函数函数名前缀为Test测试程序的一些逻辑行为是否正确
基准函数函数名前缀为Benchmark测试函数的性能
示例函数函数名前缀为Example为文档提供示例文档

go单元测试对文件名、方法名和参数都有很严格的要求

文件名必须以xx_test.go命名
方法必须是Test[^a-z]开头
方法参数必须是t *testing.T
使用go test执行单元测试

压力测试

压力测试是用来检测函数(方法)的性能。

func Benchmark[^a-z](b *testing.B){}

5. 方法

什么是方法

方法就是一个包含了接收者的函数,接收者可以是**命名类型或者结构体类型的一个值或者是一个指针**。所有给定类型的方法属于该类型的方法集。

func (recevier type) methodName(参数列表)(返回值列表){}

注意:

  • 接收者类型不能是接口类型,因为接口是一个抽象定义,而方法却是具体实现。

  • 接收者类型也不能是指针类型,但是它可以是任何其他允许类型的指针。

  • 参数recevier可以任意命名,参数、返回值可以省略。

  • 实例value或者pointer可以调用全部的方法,编译器会自动转换。

  • 因为方法是函数,所以方法不可以重载,一个类型只能有一个给定名称的方法。但是,同样名字的方法可以在多个不同的接收者类型上存在

    • 一个类型只能有一个给定名称的方法

      type stu struct {name stringage  string
      }func (s stu) method() {s.name = "zhangsan"
      }func (s stu) method() {}// 报错
      
    • 同样名字的方法可以在多个不同的接收者类型上存在

      type stu struct {name stringage  string
      }
      type teacher struct {name   stringgender string
      }func (s stu) method() {s.name = "zhangsan"
      }
      func (t teacher) method() {}
      

方法与普通函数的区别

  1. 对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递;反之亦然。
  2. 对于方法,接收者为值类型时,可以直接用指针类型的变量调用方法;反之亦可。

匿名字段

go语言支持只提供类型而不写字段名的方式,也就是匿名字段。

当匿名字段是一个struct时,那么这个struct所拥有的全部字段以及方法都被隐式地引入了当前定义的这个struct

type person struct{name stringage intgender string
}
type student struct{person	// 匿名字段,那么student就包含了person的所有字段class stringid string
}func main(){stu := student{person{"zhangsan",23,"男"},"data191","001"}fmt.Printf("stu.name is %v\n",stu.name)fmt.Printf("stu.gender is %v\n",stu.gender)fmt.Printf("stu.class is %v\n",stu.class)stu.age = 22fmt.Printf("stu.age is %v\n",stu.age)
}// 输出信息:
// stu.name is zhangsan
// stu.gender is 男
// stu.class is data191
// stu.age is 22

stu还可以访问person作为字段名

stu.person = person{"lisi",21,"男"}
stu.person.age -= 1

但不仅仅是struct字段,所有的内置类型和自定义类型都可以作为匿名字段

type skills []string
type person struct{name stringage intgender string
}
type student struct{person	// 匿名字段,那么student就包含了person的所有字段skills	// 匿名字段,自定义类型string sliceint		// 内置类型作为匿名字段class stringid string
}func main(){stu := student{person{"zhangsan",23,"男"},"data191","001"}stu.skills = []string{"吃","喝","玩"}stu.skills = append(stu.skills,"乐")fmt.Printf("zhangsan's skills are %v\n",stu.skills)stu.int = 100fmt.Printf("stu.int:%v\n",stu.int)
}// 输出结果:
// zhangsan's skills are ["吃","喝","玩","乐"]
// stu.int:100

但是如果在person中有一个字段name,在student中也有一个字段name,那么如何处理呢?

go语言采用**最外层的优先访问**,这也就允许我们去重载通过匿名字段继承的一些字段。如果我们想访问重载后匿名类型里面的字段,也可以通过匿名字段来访问。

type person struct{name stringage intgender string
}
type student struct{person	// 匿名字段,那么student就包含了person的所有字段class stringid stringname string
}func main(){p := person{"zhangsan", 23, "男"}s := student{p, "data191", "001", "lisi"}fmt.Printf("s.name: %v\n", s.name)fmt.Printf("s.person.name: %v\n", s.person.name)
}// 输出结果:
// s.name: lisi
// s.person.name: zhangsan

关于对方法的继承,对比两个代码:

image-20220113094740569

方法集

go语言中,每个类型都有与之关联的方法,把**这个类型的所有方法**称之为类型的方法集

type student struct{name stringage int
}func (s student) showName(){fmt.Println(s.name)
}func (s *student) setName(newName string){s.name = newName
}

类型student方法集包含了showName()方法

类型*student方法集包含了showName()方法和setName()方法

因为:

  • 类型T方法集,包含所有receiver T方法
  • 类型*T方法集,包含所有receiver T方法和receiver *T方法

6. 面向对象

接口

什么是接口

go语言中的接口是一些方法的集合(method set),它指定了对象的行为。

接口是一种类型。

实现接口

一个对象只要实现了接口中的所有方法,那么就实现了这个接口。换句话说,接口就是一个需要实现的方法列表。

如下,student实现了People接口中的所有方法,所以student就实现了这个People接口:

type People interface {Speak()
}type student struct {
}func (stu student) Speak() {fmt.Println("hello")
}

接口的作用

那么实现了接口有什么用呢?

接口类型变量可以存储**任何**实现了该接口的实例。

type People interface {Speak()
}type student struct {
}type teacher struct {
}func (stu student) Speak() {fmt.Println("i'm a student")
}func (tea teacher) Speak() {fmt.Println("i'm a teacher")
}func main(){var p Peoplestu := student{}tea := teacher{}p = stup.Speak()p = teap.Speak()
}// 输出结果为:
// i'm a student
// i'm a teacher

值接收者和指针接收者实现接口的区别

**值接收者**实现接口
type People interface {Speak()
}type student struct {
}func (stu student) Speak() {fmt.Println("i'm a student")
}func main(){var p Peoplestu := student{}p = stu		// 接收student类型p.Speak()p = &stu	// 接收*student类型p.Speak()
}// 输出结果:
// i'm a student
// i'm a student

使用**值接收者实现接口之后,不管是student结构体类型的变量还是student结构体指针类型的变量都可以赋值给People接口**变量。

**指针接收者**实现接口
type People interface {Speak()
}type student struct {
}func (stu *student) Speak() {fmt.Println("i'm a student")
}func main(){var p Peoplestu := student{}p = stu		// 接收student类型,不可以接收!!!p = &stu	// 接收*student类型,可以接收p.Speak()
}

使用**指针接收者实现接口之后,student结构体类型的变量无法赋值给People接口变量,student结构体指针类型的变量可以复制给People接口**变量。

此时,People接口变量就只能存储**student结构体指针**类型的值

类型和接口的关系

一个类型实现多个接口

一个类型可以实现多个接口,而接口之间彼此独立,不知道对方的实现。

type People interface {Speak()
}type children interface {Play()
}type student struct {
}func (stu student) Speak() {fmt.Println("i'm a student")
}func (stu student) Play() {fmt.Println("i like playing")
}func main(){s := student{}s.Speak()s.Play()
}// 输出结果:
// i'm a student
// i like playing

多个类型实现一个接口

type People interface {Speak()
}type student struct {
}type teacher struct {
}func (stu student) Speak() {fmt.Println("i'm a student")
}func (tea teacher) Speak() {fmt.Println("i'm a teacher")
}func main(){var p Peoplestu := student{}tea := teacher{}p = stup.Speak()p = teap.Speak()
}// 输出结果为:
// i'm a student
// i'm a teacher

一个接口的方法,不一定是一个类型完全实现,接口的方法可以通过在类型中嵌入其他类型或者结构体来实现。

如下,一个洗衣机包含了洗衣和烘干的功能,我们通过两个类型来将其实现

type WashingMachine interface {washing()dry()
}type wash truct {
}type Haier truct {wash
}func (w wash) washing() {fmt.Println("function is wash")
}func (h Haier) dry() {fmt.Println("function is dry")
}

接口嵌套

接口和接口之间可以通过嵌套创建新的接口

type Sayer interface {say()
}type Mover interface {move()
}type Animal interface {SayerMover
}

空接口

空接口是指没有定义任何方法的接口,因此任何类型都实现了空接口。

func main() {var x interface{}s := "nihao"i := 1x = sx = i
}

空接口的应用

使用空接口可以接收任意类型的函数参数

func show(a interface{}) {}
使用空接口实现map、slice存储任意类型值
func main() {sli2 := []interface{}{1, 2, 3}map1 := map[string]interface{}{"name": "zhangsan","age":  2,}
}

类型断言

空接口可以存储任何类型的值,那么我们怎么获取我们存储的具体数据呢?

一个接口的值由**具体类型具体类型的值**两部分组成。这两部分分别称为接口的动态类型和动态值。

想要判断空接口中的值这个时候就可以使用类型断言,格式为x.(T),具体如下:

func main() {sli2 := []interface{}{1, 2, 3}_, ok := sli2[2].(string)fmt.Println(ok)
}

关于接口需要注意的

关于接口需要注意的是,只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口。不要为了接口而写接口,那样只会增加不必要的抽象,导致不必要的运行时损耗。

7. 标准库

反射

反射是指在程序运行期间对程序本身进行访问和修改的能力

获取类型:reflect.TypeOf(a)

获取值:reflect.ValueOf(a)

空接口和反射

设置值(函数接收者为指针类型):reflect.ValueOf(a).Elem().SetInt()

func reflect_getTypeAndValue(a interface{}) {t := reflect.TypeOf(a)fmt.Printf("类型是:", t)println()k := t.Kind() // 可以获取具体的类型fmt.Printf("具体类型是:", k)println()v := reflect.ValueOf(a)fmt.Printf("值是:", v)println()fmt.Printf("值是:", v.Int())
}
func reflect_setValue(a interface{}) {v := reflect.ValueOf(a)k := v.Kind() // 可以获取具体的类型switch k {case reflect.Int64:v.SetInt(12)println()fmt.Printf("修改后的值是:", v)case reflect.Ptr:v.Elem().SetInt(15)println()fmt.Printf("修改后的值是:", v)}
}func main(){reflect_getTypeAndValue(num)reflect_setValue(&num)
}

结构体与反射

获取所有字段的个数:reflect.TypeOf(o).NumField()获取字段:reflect.TypeOf(o).Field(index)获取字段的名字:reflect.TypeOf(a).Field(index).Name获取字段的类型:reflect.TypeOf(a).Field(index).Type获取字段的值:reflect.ValueOf(o).Field(index).Interface()修改字段的值(函数接收者为<font color='red'>指针类型</font>):reflect.ValueOf(0).Elem().FieldByName(fieldName).SetString()获取字段的tag:reflect.ValueOf(o).Type().Elem().Field(index).Tag.Get(tagName)获取方法的个数:reflect.TypeOf(o).NumMethod()获取方法:reflect.TypeOf(o).Method(index)获取方法的名字:reflect.TypeOf(o).Method(index).Name获取方法的调用类型和参数类型:reflect.TypeOf(o).Method(index).Type调用方法:reflect.ValueOf(o).MethodByName(methodName).Call( []reflect.Value{reflect.ValueOf(value) )
type User struct {Id   intName stringAge  int
}type Boy struct {UserAddr string
}func (u User) Hello(name string) {fmt.Println("hello:", name)
}
// 查看所有字段的名字、类型和值
func Poni(o interface{}) {t := reflect.TypeOf(o)fmt.Println("类型:", t)fmt.Println("字符串类型:", t.Name())v := reflect.ValueOf(o)fmt.Println("值:", v)for i := 0; i < t.NumField(); i++ {f := t.Field(i)fmt.Printf("%s : %v\t", f.Name, f.Type)val := v.Field(i).Interface()fmt.Println("val:", val)}fmt.Println("=================================")for i := 0; i < t.NumMethod(); i++ {m := t.Method(i)fmt.Print(m.Name)fmt.Println(" ", m.Type)}
}
// 查看匿名字段
func Poni2(b interface{}) {t := reflect.TypeOf(b)v := reflect.ValueOf(b)//fmt.Println(v)fmt.Printf("v.Field(0):%v\n", v.Field(0))for i := 0; i < t.NumField(); i++ {f := t.Field(i)fmt.Printf("%s %s\t", f.Name, f.Type)val := v.Field(i).Interface()fmt.Printf("%s \n", val)}fmt.Println("=========================================")for i := 0; i < t.NumMethod(); i++ {m := t.Method(i)fmt.Printf("%s %s\n", m.Name, m.Type)}
}
// 修改结构体的值
func struct_SetValue(o interface{}) {v := reflect.ValueOf(o)v = v.Elem()f := v.FieldByName("Name")if f.Kind() == reflect.String {f.SetString("wangwu")}
}
// 调用方法
func struct_methodXfer(o interface{}) {v := reflect.ValueOf(o)m := v.MethodByName("Hello")args := []reflect.Value{reflect.ValueOf("kugou")}m.Call(args)
}
// 获取字段的tag
func struct_getFieldTag(o interface{}) {t := reflect.TypeOf(o)f := t.Elem().Field(0)fmt.Println(f.Tag.Get("json"))fmt.Println(f.Tag.Get("db"))
}

  1. goroutine是Go语言中的轻量级线程实现。 ↩︎ ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/550653.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git@github.com:Permission denied(publickey).fatal: Could not read form remote repository错误

文章目录前言问题分析解决方法配置客户端配置服务端验证前言 在使用goland从github下载依赖时(git clone github.com/gin-gonic/gin)出现gitgithub.com:Permission denied(publickey).fatal: Could not read form remote repository错误。 问题分析 Permission denied(publi…

go出现missing go.sum entry for module providing package 错误

文章目录前言问题分析解决方法前言 从github下载了别人的代码后直接执行&#xff0c;报missing go.sum entry for module providing package错误 问题分析 代码中使用了第三方库&#xff0c;但是go.mod并没有跟着更新 解决方法 在项目目录下打开终端&#xff0c;执行go mo…

的计时器设置_如何选择最适合自己的计时器?

本文作者是Ultraman&#xff0c;他为了找到最适合自己的计时方法&#xff0c;试验了十多种计时器或者沙漏&#xff0c;总结出了非常棒的经验&#xff01;相信本文一定会对你有所帮助。 ——李长太大家对番茄工作法一定已经不陌生了&#xff0c;那么进行番茄工作法的时候&#x…

npm install报错 npm ERR,code ERESOLVE npm ERR,ERESOLVE unable to resolve dependency tree

文章目录前言问题分析解决方法转载于前言 在下载npm时报错npm ERR! code ERESOLVE npm ERR! ERESOLEVE unable to resolve dependency tree 问题分析 我的npm版本为8.x&#xff0c;npm6.x之后的版本更加严格了&#xff0c;所以会报错 解决方法 方法1&#xff0c;降级到np…

卡顿严重_微软Win 10游戏模式致《使命召唤:战区》等游戏出现严重卡顿现象

IT之家5月8日消息 据Windowslatest报道&#xff0c;有部分用户报告称Windows 10游戏模式可能对某些硬件的游戏性能产生负面影响。一位用户表示&#xff0c;启用游戏模式后&#xff0c;搭载Radeon RX 5700 XT、RX 480、R9 290等AMD显卡设备以及GTX 980和GTX 1080 Ti等Nvidia显卡…

MySQL的MVCC是什么

文章目录MVCC是什么MVCC的作用MVCC的实现原理Read View是什么Read View如何判断某个版本可以访问MVCC是什么 MVCC(Multiversion concurrency control)是同一行数据保留多版本的一种方式&#xff0c;进而实现并发控制。 在查询时&#xff0c;通过read view和版本链找到对应版本…

go中make、new和直接var的区别

文章目录直接varmakenew小结直接var func main(){var sli []intfmt.Println(sli) // 打印结果为&#xff1a;[]fmt.Println(len(sli)) // 打印结果为&#xff1a;0fmt.Println(cap(sli)) // 打印结果为&#xff1a;0fmt.Println(sli[0]) // panic: index out of…

论述类文本知识框架_高考语文“论述类文本阅读”:三步走,拿满分

【原创首发】新的学期开始了。高三的定位考试也结束了。成绩下来了&#xff0c;有的同学拿着卷子找着我&#xff1a;“老师&#xff0c;你看看&#xff0c;我第一道大题三道错了两道&#xff0c;咋办呀&#xff1f;”高考语文试卷的第一大道试题”论述类文本阅读“这道题&#…

mysql数据自定义随机_Mysql 自定义随机字符串

前几天在开发一个系统&#xff0c;需要用到随机字符串&#xff0c;但是mysql的库函数有没有直接提供&#xff0c;就简单的利用现有的函数东拼西凑出随机字符串来.下面简单的说下实现当时.1.简单粗暴.select ..., substring(MD5(RAND()),floor(RAND()*26)1,6) as rand_str .....…

php连接mysql乱码原因_PHP连接MYSQL出现乱码的原因与解决办法

PHP连接mysql出现乱码的原因与解决方法解决MySql数据库乱码的一个首要前提是保证 数据库数据表前端显示 编码一致&#xff0c;国内项目一般统一设定为GB2312或GBK&#xff0c;而国际化项目则一般使用utf8。另外&#xff0c;字符集设定完毕之后记得重启目标机MySql服务。PHP连接…

linux查看非注释行_Linux筛除空行和注释行的技巧

CentOS7.3学习笔记总结(四十一)- Linux筛除空行和注释行的技巧 在linux系统中的很多文件,写程序的人为了方便查阅整篇文档,写了很多注释,加了很多空行,虽然方便了整体的阅读,但是参数的添加、删除、修改等就没有那么友好了,我们就需要利用命令行筛选出没有这些内容的内容…

mysql数据迁移双写_数据迁移类测试策略

二、迁移类测试策略1、概述随着业务需求或数据量增长到一定程度&#xff0c;往往需要进行数据库切换&#xff0c;这里就伴随这数据迁移。关键字&#xff1a; 全量数据迁移&#xff0c;增量数据迁移&#xff0c;分库分表&#xff0c;数据双写&#xff0c;oracle、mysql、hbase……

where is null mysql_SQL中WHERE变量IS NULL条件导致全表扫描问题的解决方法

SET SQL SELECT * FROM Comment with(nolock) WHERE 11And (ProjectIds Is Null or ProjectId ProjectIds)And (Scores is null or Score Scores)印象中记得&#xff0c;以前在做Oracle开发时&#xff0c;这种写法是会导致全表扫描的&#xff0c;用不上索引&#xff0c;不知道…

lambda的java_一分钟搞明白java8中的lambda

项目结构是这样的User是一个普通的pojo类UserCompare是一个实现了Comprator的类现在我们有一个需求&#xff1a;给一个user组成的list 按照user的年龄排序。实现不难&#xff0c;代码如下&#xff1a;这种方法由于sort方法的第二个参数是Comparator 所以你要写一个实现类(我这里…

读芯术python教程答案_攻略Python的免费书单:走进编程,从这五本书开始

全文共1245字&#xff0c;预计学习时长5分钟图源&#xff1a;unsplashPython一向是数据科学家最青睐的编程语言&#xff0c;它的语法相对简单、易于学习。除了机器学习数据库之外&#xff0c;还有非常活跃的开发人员社区&#xff0c;维护着各种库&#xff0c;用于数据分析、操作…

JAVA minaio模型_分布式系统之Java IO模型

1.正确理解IO定义IO涉及两个系统对象&#xff0c;一个是用户进程&#xff0c;一个是系统内核阻塞IO和非阻塞IO 针对是对用户进程来讲的调用函数。同步IO和异步IO针对的是系统内核。select,poll,epoll是Linux系统使用最多的IO多路复用机制&#xff0c;采用的都是同步IO。IO读取过…

java 写一个计算器_java编写一个计算器类

展开全部import java.awt.BorderLayout;import java.awt.Color;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JFrame;import javax.swin…

java文本框背景_用Java编写小程序(包含组合框下拉和文本框)变换背景颜色

展开全部代码如下&#xff1a;import java.awt.Color;import java.awt.Dimension;import java.awt.FlowLayout;import java.util.HashMap;import java.util.Map;import javax.swing.JComboBox;import javax.swing.JFrame;import javax.swing.JTextField;public class App exten…

关于java_关于Java基础

一、方法的重载与重写方法重载(overload)是让类以统一的方式处理不同类型数据的一种手段。调用方法时通过传递给它们的不同个数和类型的参数来决定具体使用哪个方法&#xff0c;这就是多态性。所谓方法重载是指在一个类中&#xff0c;多个方法的方法名相同&#xff0c;但是参数…

yii2 提供接口给java_yii2写api接口步骤

yii2写api接口步骤Yii2如何实现RESTful风格的API(推荐&#xff1a;《YII教程》 )1、建立单独的应用程序为了增加程序的可维护性&#xff0c;易操作性&#xff0c;我们选择新建一套应用程序&#xff0c;这也是为了和前台应用、后台应用区分开操作。在WEB前端(frontend)和后端(ba…